Bagaimana cara menggabungkan string dan variabel di PowerShell?

610

Misalkan saya memiliki cuplikan berikut:

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

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

Saya berharap cuplikan ini ditampilkan:

42 - Slim Shady - Eminem

Tapi itu justru menunjukkan:

42 + - + Slim Shady + - + Eminem

Yang membuat saya berpikir +operator tidak cocok untuk menggabungkan string dan variabel.

Bagaimana Anda harus mendekati ini dengan PowerShell?

Ninja Cowgirl
sumber
28
Kode Anda berfungsi jika semua elemen adalah string dan Anda menyertakan ekspresi dalam tanda kurung: di Write-host ($assoc.Id.ToString() + " - " + $assoc.Name + " - " + $assoc.Owner) sini $ assoc.Id adalah Int32jadi kita harus menggunakan representasi string-nya. Kalau tidak, PS mencoba melakukan penambahan aritmatika alih-alih rangkaian.
bouvierr
5
Mengingat jumlah penayangan yang saya pikir tepat untuk memperbaiki teks dari pertanyaan ini, meskipun suntingan saya mengubah isinya sedikit. Saya sudah mencoba untuk menjaga terminologi / kata-kata dan semangat pertanyaan tetap utuh, sambil memperbaikinya sehingga dapat dibuka kembali.
Jeroen

Jawaban:

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

Lihat Spesifikasi sub-ekspresi Windows PowerShell Language Spesifikasi Versi 3.0 , p34,.

David Brabant
sumber
1
Teknik ini juga bekerja dengan Write-Output et al , jadi mungkin ini yang paling berguna untuk dimiliki di kotak peralatan Anda.
Fenton
4
Mengapa $ ($ name) vs hanya $ name? Apakah ini hanya defensif dengan cara yang sama seperti di bash menggunakan $ {name}?
Danny Staple
73
Ini bukan penggabungan secara teknis.
TravisEz13
8
@DannyStaple pertanyaannya telah diedit begitu banyak sehingga jawabannya tidak masuk akal lagi. Dalam contoh teduh ramping, ya "... $name ..."akan bekerja semua sama, tetapi dalam pertanyaan asli yang dijawab jawaban ini, pertanyaannya adalah bagaimana mengakses properti objek. jadi jika $name.id -eq 42kemudian "... $name.id ..."tidak akan berfungsi seperti yang Anda inginkan karena itu akan membuat suka ... @{id=42}.id ...daripada yang diinginkan ... 42 ...Untuk itu, gunakan metode jawabannya "... $($name.id) ...". Saya mem-bookmark pertanyaan untuk diedit nanti.
Jeff Puckett
3
Terima kasih banyak telah menunjukkan saya ke Spesifikasi Bahasa PowerShell. Sebagai seorang pemula, saya selalu bingung mengapa PowerShell tidak disertai dengan tutorial resmi. Spesifikasi bahasa ini terlihat seperti apa yang saya cari. Terima kasih lagi!
RayLuo
256

Tampaknya tidak ada yang menyebutkan perbedaan antara tanda kutip tunggal dan ganda. (Saya menggunakan PowerShell 4).

Anda dapat melakukan ini (seperti yang dikatakan @Ben):

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

Atau Anda dapat melakukan ini:

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

Kutipan tunggal untuk literal, tolong berikan string persis seperti ini. Kutipan ganda untuk ketika Anda ingin beberapa pra-pemrosesan dilakukan (seperti variabel, karakter khusus dll)

Begitu:

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

Sedangkan:

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

( http://ss64.com/ps/syntax-esc.html Saya menemukan referensi yang bagus).

TinyRacoon
sumber
1
Bekerja dengan 1.0 juga.
Smit Johnth
134

Salah satu caranya adalah:

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

Yang lain adalah:

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

Atau hanya (tapi saya tidak suka;)):

Write-host $assoc.Id  "  -  "   $assoc.Name  "  -  "  $assoc.Owner
CB.
sumber
7
Saya tidak berpikir yang terakhir bekerja persis seperti yang Anda harapkan. Lihat pastebin di sini . Powershell akan menambahkan satu (walaupun Anda memiliki dua ruang di sini) ke output untuk spasi putih di antara $assoc.Iddan "(et al). Artinya, opsi 1 memberi Anda Id__-__Name__-__Owner(dua spasi di setiap sisi masing-masing -), tetapi opsi 3 memberi Id___-___Name___-___Owner( tiga spasi).
ruffin
4
Mungkin pastebin yang lebih bermanfaat . $assoc.Id"###"$assoc.Name akan menambah spasi di kedua sisi ###, di mana "$($assoc.Id)###$($assoc.Name)" tidak .
ruffin
1
yang kedua meyakinkan saya PowerShell adalah apa yang saya butuhkan untuk tujuan saya - terima kasih!
MaVCArt
123

Anda juga bisa menggunakan -join

Misalnya

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

Akan menetapkan "John" ke $ name.

Jadi untuk output, dalam satu baris:

Write-Host (-join("Jo", "h", "n"))
banyak jalan
sumber
setidaknya yang ini bisa digunakan di foreach
dEmigOd
68

Cobalah membungkus apa pun yang ingin Anda cetak dalam tanda kurung:

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

Kode Anda sedang ditafsirkan sebagai banyak parameter yang diteruskan ke Write-Host. Membungkusnya di dalam tanda kurung akan menggabungkan nilai-nilai dan kemudian meneruskan nilai yang dihasilkan sebagai parameter tunggal.

goric
sumber
3
+1, saya lebih suka format ini ketika menggunakan metode lain seperti Write-Debugatau Write-Verboseuntuk menyertakan tanda kutip ganda dan nilai variabel, sepertiWrite-Debug ('Running "cmdlet" with parameter $MyVar = ' + $MyVar + " at time " + (Get-Date -DisplayHint Time))
IT Bear
Ya, ini adalah penggabungan string. Itu tidak menambahkan baris baru atau spasi tambahan. Ini memungkinkan Anda menggunakan string yang dikutip tunggal atau ganda.
LexieHankins
Trik ini adalah penggabungan benar dan memungkinkan Anda untuk melakukan string multi-line, seperti yang Anda lakukan di .net. Sangat bagus untuk melakukan pernyataan SQL multiline! Mengapa PowerShell tidak melakukan ini secara default !?
Brain2000
Ada banyak cara yang harus dilakukan. Tapi ini adalah jawaban sejati dari rangkaian string.
chingNotCHing
32

Pilihan lain adalah:

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

Metode "terbaik" mungkin yang disarankan CB:

Write-host "$($assoc.Id)  -  $($assoc.Name)  -  $($assoc.Owner)"
Frode F.
sumber
3
Anda perlu menambahkan StringBuilderopsi jika Anda gila gila. ; ^)
ruffin
2
pasti ada cara untuk menyalurkan properti yang diinginkan ke file eksternal, kemudian deserialize mereka menjadi serangkaian komponen yang bergabung dengan tanda hubung (?)
Code Jockey
Sulit membayangkan jurang yang lebih buruk dari ini. String tidak dapat diubah, sehingga setiap operasi penggabungan pada kenyataannya menghasilkan string baru, menyalin karakter dari yang asli.
wombatonfire
22

Anda perlu menempatkan ekspresi dalam tanda kurung untuk menghentikannya diperlakukan sebagai parameter berbeda ke cmdlet:

Write-host ($assoc.Id + "  -  "  + $assoc.Name + "  -  " + $assoc.Owner)
Richard
sumber
Ini wajib untuk Write-Debug
Frank
19

Sementara ekspresi:

"string1" + "string2" + "string3"

akan menyatukan senar. Anda harus meletakkan $ di depan tanda kurung untuk membuatnya mengevaluasi sebagai argumen tunggal ketika diteruskan ke perintah PowerShell. Contoh:

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

Sebagai bonus, jika Anda ingin span beberapa baris, maka Anda perlu menggunakan sintaks backtick ackward di akhir baris (tanpa spasi atau karakter di sebelah kanan backtick). Contoh:

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

(Sebenarnya, saya pikir Powershell saat ini diimplementasikan sedikit salah dengan memerlukan back-ticks yang tidak perlu di antara tanda kurung. Jika Microsoft hanya akan mengikuti aturan Parenthesis "Python" atau "TCL" yang memungkinkan Anda untuk menempatkan baris baru sebanyak yang Anda inginkan antara mulai dan mengakhiri kurung maka mereka akan memecahkan sebagian besar masalah yang orang tidak suka tentang PowerShell terkait dengan kelanjutan garis, dan rangkaian string. Saya telah menemukan bahwa Anda dapat meninggalkan tanda centang-off kadang-kadang pada kelanjutan garis antara tanda kurung, tetapi itu benar-benar flakey dan tidak dapat diprediksi jika akan bekerja .. lebih baik hanya menambahkan backticks.)

Bill Moore
sumber
13

Berikut ini cara lain sebagai alternatif:

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

Saya hanya ingin membawa cara lain untuk melakukan ini menggunakan .NET String.Format :

$name = "Slim Shady"
Write-Host ([string]::Format("My name is {0}", $name))
Martin Brandl
sumber
2
Apakah ada keuntungan menggunakan .NET String.Formatdaripada yang lama "{0}" -f $var? Saya tidak melihat gunanya menggunakan kode .NET di mana PowerShell biasa dapat melakukan pekerjaan ...
Dinei
4
@DineiRockenbach Mungkin tidak. Hanya ingin memunculkan contoh lain.
Martin Brandl
9

(Versi PS saat ini 5.1.17134.407)

Semuanya dikatakan dan dilakukan sekarang, saya rasa tetapi ini juga berfungsi seperti sekarang:

$myVar = "Hello"

echo "${myVar} World"

Catatan: ini hanya bekerja dengan tanda kutip ganda

Benjamin
sumber
7

Semua jawaban ini tampaknya sangat rumit. Jika Anda menggunakan ini dalam skrip PowerShell Anda bisa melakukan ini:

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

Ini akan menampilkan

Nama saya Slim Shady

Perhatikan bagaimana spasi diletakkan di antara kata-kata untuk Anda

ditinggikan
sumber
6

String gabungan seperti di hari-hari DOS. Ini adalah masalah besar untuk penebangan jadi di sini Anda mulai:

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

Write-Output "$($strDate.Year)$($strDate.Month)$($strDate.Day)"
Write-Output $strday
Kelly Davis
sumber
Untuk kencan, saya pikir toStringpilihannya lebih mudah:(Get-Date).toString('yyyyMMdd')
Tony
6

Saya sepertinya bergumul dengan ini (dan banyak hal tidak intuitif lainnya) setiap kali saya menggunakan PowerShell dari waktu ke waktu, jadi saya sekarang memilih:

[string]::Concat("There are ", $count, " items in the list")
Luke Puplett
sumber
1
ini mengembalikan System.Object, fyi.
Barry
4

Write-Host dapat digabungkan seperti ini juga:

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

Ini adalah cara paling sederhana, IMHO.

Mordechai
sumber
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
blayderunner123
sumber
2

Jika Anda menggabungkan string untuk membangun path file, gunakan perintah join-path:

join-path C:\temp "MyNewFolder"

Ini akan secara otomatis menambahkan garis miring / garis miring yang sesuai untuk Anda, yang membuat segalanya jauh lebih mudah.

Saya minta maaf jika ini terlalu di luar topik, tetapi saya pikir ini mungkin bisa membantu.
Jika saya tidak menggunakan PowerShell untuk sementara waktu, kadang-kadang saya akan lupa itu ada dan mulai mencari operator gabungan.

squicc
sumber
0

Anda juga bisa mendapatkan akses ke metode C # /. NET, dan yang berikut ini juga berfungsi:

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

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

Output:

Slim Shady, The real slim shady
Ian Robertson
sumber
-2

Hanya untuk bersenang-senang. Anda juga dapat mengakses nilai-nilai PSObject secara langsung seperti di bawah ini:

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

Tetapi jika Anda tidak menentukan bahwa objek harus dipesan, Powershell akan menampilkan nilai-nilai dalam urutan acak. Jadi sebaiknya tambahkan flag [dipesan]

$assoc = [pscustomobject] [ordered] @{
    Id = 42
    Name = "Slim Shady"
    Owner = "Eminem"
}
R.Amersfoort
sumber