Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Esistono molti modi per usare le variabili nelle stringhe. Chiamo questa sostituzione di variabili, ma mi riferisco a ogni volta che vuoi formattare una stringa per includere i valori delle variabili. Questo è qualcosa che spesso mi trovo a spiegare ai nuovi scripter.
Nota
La versione originale di questo articolo è apparsa nel blog scritto da @KevinMarquette. Il team di PowerShell ringrazia Kevin per aver condiviso questo contenuto con noi. Consultare il suo blog all'indirizzo PowerShellExplained.com.
Concatenazione
La prima classe di metodi può essere definita concatenazione. Si tratta fondamentalmente di prendere diverse stringhe e unirle. Esiste una lunga cronologia dell'uso della concatenazione per compilare stringhe formattate.
$name = 'Kevin Marquette'
$message = 'Hello, ' + $name
La concatenazione funziona correttamente quando sono presenti solo alcuni valori da aggiungere. Ma questo può diventare complicato rapidamente.
$first = 'Kevin'
$last = 'Marquette'
$message = 'Hello, ' + $first + ' ' + $last + '.'
Questo semplice esempio è già più difficile da leggere.
Sostituzione di variabili
PowerShell offre un'altra opzione più semplice. È possibile specificare le variabili direttamente nelle stringhe.
$message = "Hello, $first $last."
Il tipo di virgolette usate intorno alla stringa fa la differenza. Una stringa tra virgolette doppie consente la sostituzione, ma non una singola stringa tra virgolette. Ci sono volte che vuoi uno o l'altro in modo da avere un'opzione.
Sostituzione dei comandi
Quando si inizia a provare a ottenere i valori delle proprietà in una stringa, è difficile. Questo è il punto in cui molte persone nuove si confondono. Prima di tutto lasciate che vi mostri cosa pensano dovrebbe funzionare (e a prima vista sembra quasi che dovrebbe).
$directory = Get-Item 'C:\windows'
$message = "Time: $directory.CreationTime"
Ti aspetti di ottenere il CreationTime dal $directory, ma invece ottieni il Time: C:\windows.CreationTime come valore. Il motivo è che questo tipo di sostituzione vede solo la variabile di base. Considera il punto come parte della stringa in modo che interrompa la risoluzione del valore in modo più profondo.
È sufficiente che questo oggetto restituisca una stringa come valore predefinito quando viene inserita in una stringa.
Alcuni oggetti forniscono invece il nome del tipo, ad esempio System.Collections.Hashtable. Solo qualcosa a cui prestare attenzione.
PowerShell consente di eseguire l'esecuzione dei comandi all'interno della stringa con una sintassi speciale. In questo modo è possibile ottenere le proprietà di questi oggetti ed eseguire qualsiasi altro comando per ottenere un valore.
$message = "Time: $($directory.CreationTime)"
Questo funziona bene per alcune situazioni, ma può diventare altrettanto pazzesco come la concatenazione se si dispone di poche variabili.
Esecuzione di comandi
È possibile eseguire comandi all'interno di una stringa. Anche se ho questa opzione, non mi piace. Diventa ingombrato rapidamente e difficile da eseguire il debug. O eseguo il comando e salvo in una variabile oppure uso una stringa di formato.
$message = "Date: $(Get-Date)"
Stringa di formato
.NET ha un modo per formattare le stringhe che trovo abbastanza facile da usare. Prima, ti mostrerò il metodo statico, quindi ti mostrerò la scorciatoia di PowerShell per fare la stessa cosa.
# .NET string format string
[string]::Format('Hello, {0} {1}.',$first,$last)
# PowerShell format string
'Hello, {0} {1}.' -f $first, $last
Ciò che accade qui è che la stringa viene analizzata per i token {0} e {1}, quindi usa tale numero per selezionare i valori forniti. Se si desidera ripetere un valore nella stringa, è possibile riutilizzare tale numero di valori.
Più complicata è la stringa, maggiore è il valore che si ottiene da questo approccio.
Formattare i valori come matrici
Se la riga di formato diventa troppo lunga, è possibile inserire prima i valori in una matrice.
$values = @(
"Kevin"
"Marquette"
)
'Hello, {0} {1}.' -f $values
Questo non è splatting perché sto passando l'intero array, ma l'idea è simile.
Formattazione avanzata
Queste opzioni sono state chiamate intenzionalmente come provenienti da .NET perché ci sono molte opzioni di formattazione già ben documentate su di esso. Esistono modi predefiniti per formattare vari tipi di dati.
"{0:yyyyMMdd}" -f (Get-Date)
"Population {0:N0}" -f 8175133
20211110
Population 8,175,133
Non entrerò nei dettagli, ma volevo solo farti sapere che questo è un motore di formattazione molto potente, se ne hai bisogno.
Unione di stringhe
In alcuni casi si vuole concatenare un elenco di valori insieme. C'è un operatore -join che può farlo per te. Consente anche di specificare un carattere da unire tra le stringhe.
$servers = @(
'server1'
'server2'
'server3'
)
$servers -join ','
Se si desidera -join alcune stringhe senza un separatore, è necessario specificare una stringa vuota ''.
Ma se questo è tutto ciò di cui hai bisogno, c'è un'opzione più veloce.
[string]::Concat('server1','server2','server3')
[string]::Concat($servers)
Vale anche la pena sottolineare che è anche possibile -split stringhe.
Join-Path
Questo è spesso trascurato, ma un ottimo cmdlet per la creazione di un percorso di file.
$folder = 'Temp'
Join-Path -Path 'C:\windows' -ChildPath $folder
La cosa positiva di questo è che gestisce correttamente le barre rovesciate quando combina i valori. Ciò è particolarmente importante se si accettano valori da utenti o file di configurazione.
Questo funziona anche con Split-Path e Test-Path. Tratto anche questi argomenti nel mio post sulla lettura e il salvataggio di file .
Le stringhe sono matrici
Devo menzionare l'aggiunta di stringhe qui prima di andare avanti. Tenere presente che una stringa è solo una matrice di caratteri. Quando si aggiungono più stringhe, ogni volta viene creata una nuova matrice.
Esaminare questo esempio:
$message = "Numbers: "
foreach($number in 1..10000)
{
$message += " $number"
}
Sembra molto semplice, ma ciò che non si vede è che ogni volta che viene aggiunta una stringa a $message che viene creata un'intera nuova stringa. La memoria viene allocata, i dati vengono copiati e quello precedente viene rimosso.
Non è un grosso problema quando viene fatto solo alcune volte, ma un ciclo come questo potrebbe davvero esporre il problema.
StringBuilder
StringBuilder è molto diffuso anche per la creazione di stringhe di grandi dimensioni da un sacco di stringhe più piccole. Il motivo è che raccoglie tutte le stringhe che aggiungi e le concatena solo alla fine quando recuperi il valore.
$stringBuilder = New-Object -TypeName "System.Text.StringBuilder"
[void]$stringBuilder.Append("Numbers: ")
foreach($number in 1..10000)
{
[void]$stringBuilder.Append(" $number")
}
$message = $stringBuilder.ToString()
Anche in questo caso, questo è qualcosa per cui sto raggiungendo .NET. Non lo uso più spesso, ma è bene sapere che è lì.
Delineazione con parentesi graffe
Viene usato per la concatenazione del suffisso all'interno della stringa. In alcuni casi la variabile non ha un confine di parola chiaro.
$test = "Bet"
$tester = "Better"
Write-Host "$test $tester ${test}ter"
Grazie redditor u/real_parbold per quello.
Ecco un'alternativa a questo approccio:
Write-Host "$test $tester $($test)ter"
Write-Host "{0} {1} {0}ter" -f $test, $tester
Personalmente uso la stringa di formato per questo, ma questo è bene sapere nel caso in cui lo vedi in natura.
Trovare e sostituire i token
Sebbene la maggior parte di queste funzionalità limiti la necessità di eseguire il rollback della propria soluzione, in alcuni casi è possibile che siano presenti file modello di grandi dimensioni in cui si vogliono sostituire le stringhe all'interno.
Supponiamo che tu abbia importato un modello da un file con molto testo.
$letter = Get-Content -Path TemplateLetter.txt -RAW
$letter = $letter -replace '#FULL_NAME#', 'Kevin Marquette'
Potrebbero essere presenti molti token da sostituire. Il trucco consiste nell'usare un token molto distinto che è facile da trovare e sostituire. Tendo a usare un carattere speciale su entrambe le estremità per aiutare a distinguerlo.
Ho recentemente trovato un nuovo modo per affrontare questo. Ho deciso di lasciare questa sezione qui perché questo è un modello comunemente usato.
Sostituire più token
Quando si dispone di un elenco di token che è necessario sostituire, si prende un approccio più generico. Li inserirei in una tabella hash e itererei su di essi per eseguire la sostituzione.
$tokenList = @{
Full_Name = 'Kevin Marquette'
Location = 'Orange County'
State = 'CA'
}
$letter = Get-Content -Path TemplateLetter.txt -RAW
foreach( $token in $tokenList.GetEnumerator() )
{
$pattern = '#{0}#' -f $token.key
$letter = $letter -replace $pattern, $token.Value
}
Questi token possono essere caricati da JSON o CSV, se necessario.
ExecutionContext ExpandString
Esiste un modo intelligente per definire una stringa di sostituzione con virgolette singole ed espandere le variabili in un secondo momento. Esaminare questo esempio:
$message = 'Hello, $Name!'
$name = 'Kevin Marquette'
$string = $ExecutionContext.InvokeCommand.ExpandString($message)
La chiamata a InvokeCommand.ExpandString nel contesto di esecuzione corrente utilizza le variabili dell'ambito attuale per effettuare la sostituzione. L'aspetto chiave è che il $message può essere definito molto presto prima che esistano anche le variabili.
Se ampliamo leggermente quello, possiamo eseguire questa sostituzione ripetutamente con valori diversi.
$message = 'Hello, $Name!'
$nameList = 'Mark Kraus','Kevin Marquette','Lee Dailey'
foreach($name in $nameList){
$ExecutionContext.InvokeCommand.ExpandString($message)
}
Per continuare con questa idea; è possibile importare un modello di posta elettronica di grandi dimensioni da un file di testo per eseguire questa operazione. Devo ringraziare Mark Kraus per questo suggerimento.
Qualunque cosa funzioni al meglio per te
Sono un fan dell'approccio alla stringa di formato. Lo faccio sicuramente con le stringhe più complesse o se ci sono più variabili. Per tutto ciò che è molto breve, posso usare uno di questi.
Qualsiasi altra cosa?
Ho fatto grandi progressi su questo. La mia speranza è che tu stia imparando qualcosa di nuovo.
Collegamenti
Per altre informazioni sui metodi e sulle funzionalità che rendono possibile l'interpolazione di stringhe, vedere l'elenco seguente per la documentazione di riferimento.
- La concatenazione utilizza l'operatore di addizione
- La sostituzione di variabili e comandi segue le regole di virgolette
- La formattazione usa l'operatore di formato
- La concatenazione di stringhe impiega l'operatore , ma è anche possibile leggere su
Join-Path - Le matrici sono documentate in Informazioni sulle matrici
- StringBuilder è una classe .NET, con la relativa documentazione propria
- Le parentesi graffe nelle stringhe sono descritte anche nelle regole di virgolette
- La sostituzione dei token utilizza l'operatore replace
- Il metodo
$ExecutionContext.InvokeCommand.ExpandString()include documentazione di riferimento dell'API .NET