Semua yang ingin Anda ketahui tentang substitusi variabel dalam string

Ada banyak cara untuk menggunakan variabel dalam string. Saya memanggil substitusi variabel ini tetapi saya merujuk kapan saja Anda ingin memformat string untuk menyertakan nilai dari variabel. Ini adalah sesuatu yang sering saya temukan sendiri menjelaskan kepada scripter baru.

Catatan

Versi asli artikel ini muncul di blog yang ditulis oleh @KevinMarquette. Tim PowerShell berterima kasih kepada Kevin karena telah membagikan konten ini kepada kami. Silakan lihat blognya di PowerShellExplained.com.

Rangkaian

Kelas metode pertama dapat disebut sebagai perangkaian. Ini pada dasarnya mengambil beberapa string dan menggabungkannya bersama-sama. Ada riwayat panjang menggunakan perangkaian untuk membangun string yang diformat.

$name = 'Kevin Marquette'
$message = 'Hello, ' + $name

Penggambatan berfungsi OK ketika hanya ada beberapa nilai untuk ditambahkan. Tapi ini bisa menjadi rumit dengan cepat.

$first = 'Kevin'
$last = 'Marquette'
$message = 'Hello, ' + $first + ' ' + $last + '.'

Contoh sederhana ini sudah semakin sulit dibaca.

Substitusi variabel

PowerShell memiliki opsi lain yang lebih mudah. Anda dapat menentukan variabel Anda langsung dalam string.

$message = "Hello, $first $last."

Jenis tanda kutip yang Anda gunakan di sekitar string membuat perbedaan. String yang dikutip ganda memungkinkan substitusi tetapi satu string yang dikutip tidak. Ada kalanya Anda menginginkan satu atau yang lain sehingga Anda memiliki opsi.

Penggantian perintah

Hal-hal menjadi sedikit sulit ketika Anda mulai mencoba untuk mendapatkan nilai properti ke dalam string. Di sinilah banyak orang baru tersandung. Pertama-tama biarkan saya menunjukkan kepada Anda apa yang menurut mereka harus bekerja (dan pada nilai wajah hampir terlihat seperti seharusnya).

$directory = Get-Item 'c:\windows'
$message = "Time: $directory.CreationTime"

Anda akan mengharapkan untuk mendapatkan CreationTime off dari $directory, tetapi sebaliknya Anda mendapatkan ini Time: c:\windows.CreationTime sebagai nilai Anda. Alasannya adalah bahwa jenis substitusi ini hanya melihat variabel dasar. Ini menganggap periode sebagai bagian dari string sehingga berhenti menyelesaikan nilai lebih dalam.

Kebetulan objek ini memberikan string sebagai nilai default saat ditempatkan ke dalam string. Beberapa objek memberi Anda nama jenis sebagai gantinya seperti System.Collections.Hashtable. Hanya sesuatu yang harus diwaspadai.

PowerShell memungkinkan Anda melakukan eksekusi perintah di dalam string dengan sintaks khusus. Ini memungkinkan kita untuk mendapatkan properti objek ini dan menjalankan perintah lain untuk mendapatkan nilai.

$message = "Time: $($directory.CreationTime)"

Ini berfungsi bagus untuk beberapa situasi tetapi bisa menjadi sama gilanya dengan perangkaian jika Anda hanya memiliki beberapa variabel.

Eksekusi perintah

Anda dapat menjalankan perintah di dalam string. Meskipun saya memiliki pilihan ini, saya tidak menyukainya. Ini akan berantakan dengan cepat dan sulit untuk di-debug. Saya menjalankan perintah dan menyimpan ke variabel atau menggunakan string format.

$message = "Date: $(Get-Date)"

Memformat untai (karakter)

.NET memiliki cara untuk memformat string yang menurut saya cukup mudah untuk dikerjakan. Pertama biarkan saya menunjukkan metode statis untuk itu sebelum saya menunjukkan jalan pintas PowerShell untuk melakukan hal yang sama.

# .NET string format string
[string]::Format('Hello, {0} {1}.',$first,$last)

# PowerShell format string
'Hello, {0} {1}.' -f $first, $last

Apa yang terjadi di sini adalah bahwa string diurai untuk token {0} dan {1}, maka menggunakan angka tersebut untuk memilih dari nilai yang disediakan. Jika Anda ingin mengulangi satu nilai di beberapa tempat dalam string, Anda dapat menggunakan kembali nomor nilai tersebut.

Semakin rumit string, semakin banyak nilai yang Anda dapatkan dari pendekatan ini.

Memformat nilai sebagai array

Jika baris format terlalu panjang, Anda dapat menempatkan nilai Anda ke dalam array terlebih dahulu.

$values = @(
    "Kevin"
    "Marquette"
)
'Hello, {0} {1}.' -f $values

Ini tidak bercerai karena saya melewati seluruh array masuk, tetapi idenya mirip.

Pemformatan tingkat lanjut

Saya sengaja memanggil ini sebagai berasal dari .NET karena ada banyak opsi pemformatan yang sudah di dokumentasikan dengan baik di dalamnya. Ada cara bawaan untuk memformat berbagai jenis data.

"{0:yyyyMMdd}" -f (Get-Date)
"Population {0:N0}" -f  8175133
20211110
Population 8,175,133

Aku tidak akan masuk ke mereka tapi aku hanya ingin memberitahu Anda bahwa ini adalah mesin pemformatan yang sangat kuat jika Anda membutuhkannya.

Menggabungkan string

Terkadang Anda benar-benar ingin menggabungkan daftar nilai bersama-sama. Ada -join operator yang bisa melakukannya untukmu. Bahkan memungkinkan Anda menentukan karakter untuk bergabung di antara string.

$servers = @(
    'server1'
    'server2'
    'server3'
)

$servers  -join ','

Jika Anda ingin -join beberapa string tanpa pemisah, Anda perlu menentukan string ''kosong . Tetapi jika itu saja yang Anda butuhkan, ada opsi yang lebih cepat.

[string]::Concat('server1','server2','server3')
[string]::Concat($servers)

Perlu juga dicontohkan bahwa Anda juga -split dapat melakukan string.

Join-Path

Ini sering diabaikan tetapi cmdlet yang bagus untuk membangun jalur file.

$folder = 'Temp'
Join-Path -Path 'c:\windows' -ChildPath $folder

Hal hebat tentang hal ini adalah bekerja dengan benar ketika menyaingkan nilai-nilai. Ini sangat penting jika Anda mengambil nilai dari pengguna atau file konfigurasi.

Ini juga berjalan dengan baik dengan Split-Path dan Test-Path. Saya juga membahas ini dalam posting saya tentang membaca dan menyimpan ke file.

String adalah array

Saya perlu menyebutkan menambahkan string di sini sebelum saya melanjutkan. Ingat bahwa string hanyalah array karakter. Saat Anda menambahkan beberapa string bersama-sama, array baru dibuat setiap kali.

Lihat contoh ini:

$message = "Numbers: "
foreach($number in 1..10000)
{
    $message += " $number"
}

Ini terlihat sangat mendasar tetapi yang tidak Anda lihat adalah bahwa setiap kali string ditambahkan ke $message string baru dibuat. Memori dialokasikan, data akan disalin dan yang lama dibuang. Bukan masalah besar ketika hanya dilakukan beberapa kali, tetapi perulangan seperti ini akan benar-benar mengekspos masalah.

StringBuilder

StringBuilder juga sangat populer untuk membangun string besar dari banyak string yang lebih kecil. Alasan mengapa karena hanya mengumpulkan semua string yang Anda tambahkan ke dalamnya dan hanya menggabungkan semuanya di akhir saat Anda mengambil nilai.

$stringBuilder = New-Object -TypeName "System.Text.StringBuilder"

[void]$stringBuilder.Append("Numbers: ")
foreach($number in 1..10000)
{
    [void]$stringBuilder.Append(" $number")
}
$message = $stringBuilder.ToString()

Sekali lagi, ini adalah sesuatu yang saya jangkau ke .NET untuk. Saya tidak sering menggunakannya lagi tetapi ada baiknya untuk mengetahui itu ada di sana.

Delineasi dengan kurung kurawal

Ini digunakan untuk perangkaian akhiran dalam string. Terkadang variabel Anda tidak memiliki batas kata yang bersih.

$test = "Bet"
$tester = "Better"
Write-Host "$test $tester ${test}ter"

Terima kasih /u/real_parbold untuk yang satu itu.

Berikut adalah alternatif untuk pendekatan ini:

Write-Host "$test $tester $($test)ter"
Write-Host "{0} {1} {0}ter" -f $test, $tester

Saya pribadi menggunakan string format untuk ini, tetapi ini bagus untuk mengetahui incase Anda melihatnya di alam liar.

Menemukan dan mengganti token

Meskipun sebagian besar fitur ini membatasi kebutuhan Anda untuk menggulung solusi Anda sendiri, ada kalanya Anda mungkin memiliki file templat besar di mana Anda ingin mengganti string di dalamnya.

Mari kita asumsikan Anda menarik templat dari file yang memiliki banyak teks.

$letter = Get-Content -Path TemplateLetter.txt -RAW
$letter = $letter -replace '#FULL_NAME#', 'Kevin Marquette'

Anda mungkin memiliki banyak token untuk diganti. Caranya adalah dengan menggunakan token yang sangat berbeda yang mudah ditemukan dan diganti. Saya cenderung menggunakan karakter khusus di kedua ujungnya untuk membantu membedakannya.

Saya baru-baru ini menemukan cara baru untuk mendekati ini. Saya memutuskan untuk meninggalkan bagian ini di sini karena ini adalah pola yang umum digunakan.

Mengganti beberapa token

Ketika saya memiliki daftar token yang perlu saya ganti, saya mengambil pendekatan yang lebih umum. Saya akan menempatkan mereka dalam hashtable dan iterasi atas mereka untuk melakukan penggantian.

$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
}

Token tersebut dapat dimuat dari JSON atau CSV jika diperlukan.

ExecutionContext ExpandString

Ada cara cerdas untuk menentukan string substitusi dengan tanda kutip tunggal dan memperluas variabel nanti. Lihat contoh ini:

$message = 'Hello, $Name!'
$name = 'Kevin Marquette'
$string = $ExecutionContext.InvokeCommand.ExpandString($message)

Panggilan ke .InvokeCommand.ExpandString pada konteks eksekusi saat ini menggunakan variabel dalam cakupan saat ini untuk penggantian. Hal utama di sini adalah bahwa $message dapat didefinisikan sangat awal sebelum variabel bahkan ada.

Jika kita memperluas itu hanya sedikit, kita dapat melakukan substitusi ini berulang-ulang nilai yang berbeda.

$message = 'Hello, $Name!'
$nameList = 'Mark Kraus','Kevin Marquette','Lee Dailey'
foreach($name in $nameList){
    $ExecutionContext.InvokeCommand.ExpandString($message)
}

Untuk terus melanjutkan ide ini; Anda bisa mengimpor templat email besar dari file teks untuk melakukan ini. Aku harus berterima kasih pada Mark Kraus atas saran ini.

Apa pun yang bekerja yang terbaik untuk Anda

Aku penggemar pendekatan string format. Saya pasti melakukan ini dengan string yang lebih rumit atau jika ada beberapa variabel. Pada apa pun yang sangat singkat, saya dapat menggunakan salah satu dari ini.

Ada lagi?

Aku menutupi banyak tanah untuk yang satu ini. Harapan saya adalah bahwa Anda berjalan pergi belajar sesuatu yang baru.