Come concatenare stringhe e variabili in PowerShell?


610

Supponiamo che io abbia il seguente frammento:

$assoc = New-Object psobject -Property @{
    Id = 42
    Name = "Slim Shady"
    Owner = "Eminem"
}

Write-host $assoc.Id + "  -  "  + $assoc.Name + "  -  " + $assoc.Owner

Mi aspetto che questo snippet mostri:

42 - Slim Shady - Eminem

Ma invece mostra:

42 + - + Slim Shady + - + Eminem

Il che mi fa pensare che l' +operatore non sia appropriato per concatenare stringhe e variabili.

Come dovresti affrontarlo con PowerShell?


28
Il tuo codice funziona se tutti gli elementi sono stringhe e racchiudi l'espressione tra parentesi: Write-host ($assoc.Id.ToString() + " - " + $assoc.Name + " - " + $assoc.Owner) qui $ assoc.Id è un Int32quindi dobbiamo usare la sua rappresentazione di stringa. Altrimenti PS tenta di eseguire un'aggiunta aritmetica invece di concatenazione.
bouvierr,

5
Dato il numero di visualizzazioni, ho pensato che fosse appropriato riparare il testo di questa domanda, anche se le mie modifiche hanno cambiato un po 'il contenuto. Ho cercato di mantenere intatti la terminologia / la formulazione e lo spirito della domanda, migliorandola abbastanza da consentirne la riapertura.
Jeroen,

Risposte:


667
Write-Host "$($assoc.Id) - $($assoc.Name) - $($assoc.Owner)"

Vedere le specifiche di lingua di Windows PowerShell versione 3.0 , p34, espansione delle espressioni secondarie.


1
Questa tecnica funziona anche con Write-Output et al , quindi è probabilmente la più utile da avere nella tua cassetta degli attrezzi.
Fenton,

4
Perché $ ($ name) vs solo $ name? È solo difensivo allo stesso modo di bash usando $ {name}?
Danny Staple,

73
Questa non è tecnicamente concatenazione.
TravisEz13

8
@DannyStaple la domanda è stata modificata così tanto che la risposta non ha più senso. Nel sottile esempio losco, sì "... $name ..."funzionerà lo stesso, ma nella domanda originale a cui si rivolge questa risposta, la domanda è come accedere alle proprietà dell'oggetto. quindi se $name.id -eq 42quindi "... $name.id ..."non funzionasse come vuoi perché renderebbe come al ... @{id=42}.id ...posto del desiderato ... 42 ...Per quello, usa il metodo della risposta "... $($name.id) ...". Sto aggiungendo la domanda ai segnalibri da modificare in seguito.
Jeff Puckett,

3
Grazie mille per avermi indicato la specifica del linguaggio PowerShell. Come principiante, sono sempre stato confuso sul perché PowerShell non viene fornito con un tutorial ufficiale. Questa specifica della lingua assomiglia a quello che sto cercando. Grazie ancora!
RayLuo,

256

Nessuno sembra aver menzionato la differenza tra virgolette singole e doppie. (Sto usando PowerShell 4).

Puoi farlo (come diceva @Ben):

$name = 'Slim Shady'
Write-Host 'My name is'$name
-> My name is Slim Shady

Oppure puoi farlo:

$name = 'Slim Shady'
Write-Host "My name is $name"
-> My name is Slim Shady

Le virgolette singole sono per letterale, producono la stringa esattamente in questo modo, per favore. Le virgolette doppie sono per quando si desidera eseguire una pre-elaborazione (come variabili, caratteri speciali ecc.)

Così:

$name = "Marshall Bruce Mathers III"
Write-Host "$name"
-> Marshall Bruce Mathers III

Mentre:

$name = "Marshall Bruce Mathers III"
Write-Host '$name'
-> $name

( http://ss64.com/ps/syntax-esc.html lo trovo buono come riferimento).


1
Funziona anche con 1.0.
Smit Johnth,

134

Un modo è:

Write-host "$($assoc.Id)  -  $($assoc.Name)  -  $($assoc.Owner)"

Un altro è:

Write-host  ("{0}  -  {1}  -  {2}" -f $assoc.Id,$assoc.Name,$assoc.Owner )

O semplicemente (ma non mi piace;)):

Write-host $assoc.Id  "  -  "   $assoc.Name  "  -  "  $assoc.Owner

7
Non credo che l'ultimo funzioni esattamente come ti aspetteresti. Vedi pastebin qui . Powershell aggiungerà uno (anche se ne hai due qui) all'output per lo spazio bianco tra $assoc.Ide "(et al). Cioè, l'opzione 1 ti dà Id__-__Name__-__Owner(due spazi su ciascun lato di ciascuno -), ma l'opzione 3 ti dà Id___-___Name___-___Owner( tre spazi).
ruffin,

4
Forse un pastebin più utile . $assoc.Id"###"$assoc.Name sarà aggiungere spazi su entrambi i lati del ###, in cui "$($assoc.Id)###$($assoc.Name)" non lo faranno .
Ruffin,

1
il secondo mi ha convinto che PowerShell è quello di cui avevo bisogno per i miei scopi - grazie!
MaVCArt,

123

Puoi anche usare -join

Per esempio

$name = -join("Jo", "h", "n");

Assegnerebbe "John" a $ name.

Quindi, per l'output, in una riga:

Write-Host (-join("Jo", "h", "n"))

almeno questo potrebbe essere usato in foreach
dEmigOd

68

Prova a racchiudere tutto ciò che vuoi stampare tra parentesi:

Write-host ($assoc.Id + "  -  "  + $assoc.Name + "  -  " + $assoc.Owner)

Il tuo codice viene interpretato come molti parametri a cui viene passato Write-Host. Il riavvolgimento tra parentesi concatenerà i valori e quindi passerà il valore risultante come singolo parametro.


3
+1, preferisco questo formato quando utilizzo altri metodi come Write-Debugo Write-Verboseper includere virgolette doppie e valori variabili, comeWrite-Debug ('Running "cmdlet" with parameter $MyVar = ' + $MyVar + " at time " + (Get-Date -DisplayHint Time))
IT Bear

Sì, questa è la concatenazione di stringhe. Non aggiunge nuove righe o spazi extra. Ti consente di utilizzare stringhe tra virgolette singole o doppie.
LexieHankins,

Questo trucco è una vera concatenazione e ti consente di fare stringhe multilinea, come faresti con .net. Ottimo per fare istruzioni SQL su più righe! Perché PowerShell non lo fa di default !?
Brain2000,

Ci sono molti modi per farlo. Ma questa è la vera risposta della concatenazione di stringhe.
ChingNotching

32

Un'altra opzione è:

$string = $assoc.ID
$string += " - "
$string += $assoc.Name
$string += " - "
$string += $assoc.Owner
Write-Host $string

Il metodo "migliore" è probabilmente quello suggerito dall'OdC:

Write-host "$($assoc.Id)  -  $($assoc.Name)  -  $($assoc.Owner)"

3
Devi aggiungere l' StringBuilderopzione se stai impazzendo. ; ^)
ruffin,

2
sicuramente c'è un modo per reindirizzare le proprietà desiderate in un file esterno, quindi deserializzarle in una serie di componenti uniti con trattini (?)
Codice Jockey

È difficile immaginare un approccio peggiore di così. Le stringhe sono immutabili, quindi ogni operazione di concatenazione in realtà produce una nuova stringa, copiando i caratteri di quella originale.
Wombatonfire

22

È necessario posizionare l'espressione tra parentesi per impedire che vengano trattati come parametri diversi nel cmdlet:

Write-host ($assoc.Id + "  -  "  + $assoc.Name + "  -  " + $assoc.Owner)

Questo è obbligatorio per Write-Debug
Frank

19

Mentre espressione:

"string1" + "string2" + "string3"

concatenerà le stringhe. È necessario mettere un $ davanti alla parentesi per farlo valutare come singolo argomento quando viene passato a un comando PowerShell. Esempio:

Write-Host $( "string1" + "string2" + "string3" ) 

Come bonus, se si desidera che si estenda su più righe, è necessario utilizzare la sintassi backtick ackward alla fine della riga (senza spazi o caratteri a destra del backtick). Esempio:

Write-Host $(`
    "The rain in "        +`
    "Spain falls mainly " +`
    "in the plains"       )`
    -ForegroundColor Yellow

(In realtà, penso che Powershell sia attualmente implementato in modo un po 'sbagliato, richiede inutili contraccolpi tra parentesi. Se Microsoft seguisse semplicemente le regole tra parentesi "Python" o "TCL" per consentirti di inserire tutte le nuove righe che desideri tra l'inizio e terminando la parentesi, risolverebbero la maggior parte dei problemi che non piacciono alle persone riguardo al powerhell relativo alla continuazione della linea e alla concatenazione delle stringhe. Ho scoperto che a volte è possibile lasciare le zecche sulla continuazione della linea tra parentesi, ma il suo davvero impercettibile e imprevedibile se funzionerà .. è meglio aggiungere solo i bottoncini.)


13

Ecco un altro modo in alternativa:

Write-host (" {0}  -  {1}  -  {2}" -f $assoc.Id, $assoc.Name, $assoc.Owner)

9

Voglio solo portare un altro modo per farlo usando .NET String.Format :

$name = "Slim Shady"
Write-Host ([string]::Format("My name is {0}", $name))

2
C'è qualche vantaggio nell'usare .NET String.Formatinvece della vecchia pianura "{0}" -f $var? Non vedo il punto nell'uso del codice .NET in cui PowerShell semplice può fare il lavoro ...
Dinei

4
@DineiRockenbach Probabilmente no. Volevo solo fare un altro esempio.
Martin Brandl,

9

(Versione PS corrente 5.1.17134.407)

Ormai è tutto già detto e fatto, ma funziona anche a partire da ora:

$myVar = "Hello"

echo "${myVar} World"

Nota: funziona solo con virgolette doppie


7

Queste risposte sembrano tutte molto complicate. Se lo stai usando in uno script di PowerShell puoi semplicemente farlo:

$name = 'Slim Shady'
Write-Host 'My name is'$name

Verrà emesso

Mi chiamo Slim Shady

Nota come viene inserito uno spazio tra le parole per te



6

Concatena le stringhe proprio come nei giorni DOS. Questo è un grosso problema per la registrazione, quindi ecco qui:

$strDate = Get-Date
$strday = "$($strDate.Year)$($strDate.Month)$($strDate.Day)"

Write-Output "$($strDate.Year)$($strDate.Month)$($strDate.Day)"
Write-Output $strday

Per quanto riguarda le date, penso che l' toStringopzione sia più semplice:(Get-Date).toString('yyyyMMdd')
Tony

6

Mi sembra di lottare con questo (e molte altre cose non intuitive) ogni volta che utilizzo PowerShell dopo un po 'di tempo, quindi ora opto per:

[string]::Concat("There are ", $count, " items in the list")

1
questo restituisce System.Object, fyi.
Barry,

4

Anche Write-Host può concatenare in questo modo:

Write-Host $assoc.Id" - "$assoc.Name" - "$assoc.Owner

Questo è il modo più semplice, IMHO.


2
$assoc = @{
    Id = 34
    FirstName = "John"
    LastName = "Doe"
    Owner = "Wife"
}

$assocId = $assoc.Id
$assocFN = $assoc.FirstName
$assocLN = $assoc.LastName
$assocName = $assocFN, $assocLN -Join " "
$assocOwner = $assoc.Owner

$assocJoin = $assocId, $assocName, $assocOwner -join " - "
$assocJoin
#Output = 34 - John Doe - Wife

2

Se si concatenano stringhe per creare percorsi di file, utilizzare il comando join-path:

join-path C:\temp "MyNewFolder"

Aggiungerà automaticamente le barre finali / iniziali appropriate per te, il che rende le cose molto più facili.

Mi scuso se questo è troppo fuori tema, ma ho pensato che potesse aiutare alcuni.
Se non uso PowerShell per un po ', a volte dimenticherò che esiste e inizierò a cercare gli operatori di concatenazione.


0

È inoltre possibile accedere ai metodi C # /. NET e anche le seguenti funzioni:

$string1 = "Slim Shady, "
$string2 = "The real slim shady"

$concatString = [System.String]::Concat($string1, $string2)

Output:

Slim Shady, The real slim shady

-2

Solo per divertimento. Puoi anche accedere ai valori dell'oggetto PSO direttamente come di seguito:

$assoc.psobject.Properties.value -join " - "

Ma se non si specifica che l'oggetto deve essere ordinato, Powershell visualizzerà i valori in un ordine casuale. Quindi dovrebbe aggiungere il flag [ordinato]

$assoc = [pscustomobject] [ordered] @{
    Id = 42
    Name = "Slim Shady"
    Owner = "Eminem"
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.