Çift tırnaklı bir dizede bir nesnenin özelliğini nasıl kullanabilirsiniz?


101

Takip koduna sahibim:

$DatabaseSettings = @();
$NewDatabaseSetting = "" | select DatabaseName, DataFile, LogFile, LiveBackupPath;
$NewDatabaseSetting.DatabaseName = "LiveEmployees_PD";
$NewDatabaseSetting.DataFile = "LiveEmployees_PD_Data";
$NewDatabaseSetting.LogFile = "LiveEmployees_PD_Log";
$NewDatabaseSetting.LiveBackupPath = '\\LiveServer\LiveEmployeesBackups';
$DatabaseSettings += $NewDatabaseSetting;

Bir dize çalıştırma komutundaki özelliklerden birini kullanmaya çalıştığımda:

& "$SQlBackupExePath\SQLBackupC.exe" -I $InstanceName -SQL `
  "RESTORE DATABASE $DatabaseSettings[0].DatabaseName FROM DISK = '$tempPath\$LatestFullBackupFile' WITH NORECOVERY, REPLACE, MOVE '$DataFileName' TO '$DataFilegroupFolder\$DataFileName.mdf', MOVE '$LogFileName' TO '$LogFilegroupFolder\$LogFileName.ldf'"

Geçerli olmayan $DatabaseSettingsdeğerinden ziyade değerini kullanmaya çalışır $DatabaseSettings[0].DatabaseName.
Çözümüm, yeni bir değişkene kopyalanması.

Çift tırnaklı bir dizede doğrudan nesnenin özelliğine nasıl erişebilirim?

Yanıtlar:


170

Çift tırnaklı bir dizeye bir değişken adı koyduğunuzda, bu değişkenin değeri ile değiştirilecektir:

$foo = 2
"$foo"

olur

"2"

Tek tırnak kullanmak zorunda kalmanızı istemiyorsanız:

$foo = 2
'$foo'

Bununla birlikte, özelliklere erişmek veya çift tırnaklı bir dizedeki değişkenler üzerindeki dizinleri kullanmak istiyorsanız, bu alt ifadeyi şuna eklemeniz gerekir $():

$foo = 1,2,3
"$foo[1]"     # yields "1 2 3[1]"
"$($foo[1])"  # yields "2"

$bar = "abc"
"$bar.Length"    # yields "abc.Length"
"$($bar.Length)" # yields "3"

PowerShell yalnızca bu durumlarda değişkenleri genişletir, daha fazlasını değil. Endeksler, özellikleri ve hatta komple hesaplamalar içeren daha karmaşık ifadeler, kuvvet değerlendirilmesi için, alt ifade operatörü bu içine zorunda $( )ifade içi değerlendirilir ve dizede gömülü neden olur.


Bu işe yarıyor ama merak ediyorum, ilk başta kaçınmaya çalıştığım gibi dizeleri de sıraya
dizebilir miyim

2
@ ozzy432836 Elbette yapabilirsiniz. Veya biçim dizelerini kullanın. Genellikle gerçekten önemli değil ve kişisel tercihlere bağlı.
Joey

15

@Joey doğru cevaba sahip, ancak sadece değerlendirmeyi neden zorlamanız gerektiğine dair biraz daha fazla şey eklemek için $():

Örnek kodunuz, PowerShell üreticilerinin neden genişletmeyi yalnızca değişken referanslarla sınırlamayı seçmiş olabileceğine ve özelliklere erişimi desteklemediğine işaret eden bir belirsizlik içeriyor (bir kenara: dize genişletme, ToString()nesnede yöntemi çağırarak yapılır. bazı "tuhaf" sonuçları açıklayabilir).

Örneğiniz komut satırının en sonunda yer alıyor:

...\$LogFileName.ldf

Nesnelerin özellikleri varsayılan olarak genişletilirse, yukarıdakiler şu şekilde çözülürdü:

...\

tarafından başvurulan bir amacı beri $LogFileNameadı verilen bir özelliğe sahip değildir ldf, $null(ya da boş bir dizge) değişken için ikame edilebilir olacaktır.


1
Güzel buldum. Aslında sorunun ne olduğundan tam olarak emin değildim ama özelliklere bir dizeden erişmeye çalışmak kötü kokuyordu :)
Joey

Teşekkürler beyler! Johannes, bir dizedeki özelliklere erişmenin neden kötü koktuğunu düşünüyorsunuz? Nasıl yapılmasını önerirsiniz?
caveman_dick

caveman: Bu sadece potansiyel bir hata nedeni olarak gözüme çarpan bir şeydi. Kesinlikle yapabilirsiniz ve bu tuhaf bir şey değil, ancak $ () operatörünü atladığınızda "Başarısız" diye bağırıyor çünkü işe yaramıyor. Bu yüzden cevabım, görebildiğim ilk olası başarısızlık nedenini kullanarak probleminizin ne olabileceğine dair sadece eğitimli bir tahmindi. Öyle göründüyse özür dilerim ama bu yorum herhangi bir en iyi uygulamaya atıfta bulunmuyordu.
Joey

İyi ki beni endişelendirdin! ;) Powershell'i ilk kullanmaya başladığımda bir dizedeki değişkenin biraz tuhaf olduğunu düşünmüştüm, ancak oldukça kullanışlı. Sözdizimi yardımı arayabileceğim kesin bir yer bulamadım.
caveman_dick

9

@Joey'nin iyi bir cevabı var. String.Format eşdeğeri ile daha .NET görünümünün başka bir yolu var, nesneler üzerindeki özelliklere erişirken bunu tercih ederim:

Araba ile ilgili şeyler:

$properties = @{ 'color'='red'; 'type'='sedan'; 'package'='fully loaded'; }

Bir nesne oluşturun:

$car = New-Object -typename psobject -Property $properties

Bir dizeyi enterpolate edin:

"The {0} car is a nice {1} that is {2}" -f $car.color, $car.type, $car.package

Çıktılar:

# The red car is a nice sedan that is fully loaded

Evet, özellikle .net koduna alışkınsanız, bu daha okunabilir. Teşekkürler! :)
caveman_dick

3
Biçim dizelerini ilk kullandığınızda dikkat etmeniz gereken bir şey var, bu da genellikle ifadeyi parantez içine almanız gerekeceğidir. Örneğin, write-host "foo = {0}" -f $fooPowerShell parametresi -folarak kabul edeceği için yazamazsınız . Bu örnekte yapmanız gerekecek . Bu standart PowerShell davranışıdır, ancak kayda değer. ForegroundColorwrite-hostwrite-host ( "foo = {0}" -f $foo )
andyb

Bilgiçlik taslamak gerekirse, yukarıdaki örnek "dize enterpolasyonu" değil, "bileşik biçimlendirme" dir. Powershell, C # ve VB.NET'in birincil programlama dilleri olduğu .NET'e ayrılmaz bir şekilde bağlı olduğundan, "dize enterpolasyonu" ve "enterpolasyonlu dize" (ve benzer herhangi bir şey) terimleri yalnızca bunlarda bulunan yeni $ prepended stringlere uygulanmalıdır. diller (C # 6 ve VB.NET 14). Bu dizelerde, parametre ifadeleri sayısal parametre başvuruları yerine doğrudan dizeye gömülür ve gerçek ifadeler daha sonra argümanlar olur String.Format.
Uber Kluger

@andyb, "gotchas" biçim dizesiyle ilgili. Bu aslında İfade ve Bağımsız Değişken modu arasındaki farktır (bkz. About_Parsing ). Komutlar, belirteçlere (anlamlı bir dize oluşturan karakter grupları) ayrıştırılır . Boşluk, birleştirilecek ancak aksi takdirde yok sayılacak jetonları ayırır. Komutun 1. simgesi bir sayı, değişken, ifade anahtar sözcüğü (if, while, vb.), Tekli operatör, {, vb. İse, ayrıştırma modu başka Expressiontürlüdür Argument(bir komut sonlandırıcısına kadar).
Uber Kluger

9

Dokümantasyon notu: Get-Help about_Quoting_Rulesdizi enterpolasyonunu kapsar, ancak PSv5'ten itibaren derinlemesine değildir.

Tamamlamak için Joey'in faydalı bir yanıt bir ile pragmatik özet PowerShell en hakkındaki dize genişlemesi (dize enterpolasyon çift tırnak dizeleri ( "..."aka genişletilebilir dizeleri çift tırnak içinde olmak üzere,) burada-dizeleri ):

  • Yalnızca $foo, $global:foo(veya $script:foo, ...) ve$env:PATH (ortam değişkenleri) gibi başvurular doğrudan bir "..."dizeye gömüldüğünde tanınır - yani, aşağıdakilerden bağımsız olarak yalnızca değişken başvurunun kendisi genişletilir.

    • İçin bir değişken adı belirginleştirmek dizede sonraki karakter, içine alın {ve} ; örneğin ${foo},.
      Bu, özellikle değişken adının ardından a gelirse önemlidir :, çünkü aksi takdirde PowerShell $ile :a kapsam belirticisi arasındaki her şeyi dikkate alır ve genellikle enterpolasyonun başarısız olmasına neden olur ; örneğin, "$HOME: where the heart is."kırılır, ancak "${HOME}: where the heart is."amaçlandığı gibi çalışır.
      (Alternatif olarak, `-escape :: "$HOME`: where the heart is.").

    • A $veya a'yı değişmez" olarak ele almak için, kaçış karakterinin önüne ekleyin. ( ters işaret ); Örneğin:`
      "`$HOME's value: `"$HOME`""

  • Kullanarak da dahil olmak üzere başka bir şey için dizi alt simgeler ve bir nesne değişkenin erişen özelliklerini , sen gerekir içinde ifadeyi kapamak$(...) , alt ifade operatörünü (örn "PS version: $($PSVersionTable.PSVersion)"veya "1st el.: $($someArray[0])")

    • $(...)Hatta kullanmak , tüm komut satırlarından çıktıyı çift tırnaklı dizelere (örneğin "Today is $((Get-Date).ToString('d')).") gömmenizi sağlar .
  • Enterpolasyon sonuçları, varsayılan çıktı biçimiyle aynı görünmek zorunda değildir (değişken / alt ifadeyi doğrudan konsola yazdırırsanız göreceksiniz, örneğin varsayılan biçimlendiriciyi içerir; bkz. Get-Help about_format.ps1xml):

    • Diziler dahil koleksiyonlar , öğelerin dize gösterimleri arasına tek bir boşluk yerleştirilerek dizelere dönüştürülür (varsayılan olarak; ayarlanarak farklı bir ayırıcı belirtilebilir $OFS) Örn, "array: $(@(1, 2, 3))"verimarray: 1 2 3

    • Örneklerini başka tür (kendilerini koleksiyonları olmayan koleksiyonları elemanları da dahil olmak üzere) vardır tarafından dizgelenmiş ya çağrı IFormattable.ToString()yöntemi ile sabit kültür örneğinin tip destekliyorsa, IFormattablearayüz [1] , ya da arayarak .psobject.ToString()ki çoğu durumda sadece çağırır.ToString() anlamlı bir temsil verebilecek veya vermeyebilecek temeldeki .NET türünün yöntemi [2] : (ilkel olmayan) bir tür .ToString()yöntemi özel olarak geçersiz kılmadıkça , alacağınız tek şey tam tür adıdır (örneğin, "hashtable: $(@{ key = 'value' })"verimler hashtable: System.Collections.Hashtable).

    • Konsolda olduğu gibi aynı çıktıyı elde etmek için, istenirse, öndeki ve sondaki boş satırları kaldırmak içinOut-String bir alt ifade ve boru kullanın ve uygulayın .Trim(); örneğin,
      "hashtable:`n$((@{ key = 'value' } | Out-String).Trim())"verimler:

          hashtable:                                                                                                                                                                          
          Name                           Value                                                                                                                                               
          ----                           -----                                                                                                                                               
          key                            value      
      

[1] Bu belki de şaşırtıcı davranış, kültüre duyarlı gösterimleri destekleyen türler $obj.ToString()için güncel kültüre uygun bir gösterim sağlarken "$obj"(dize enterpolasyonu) her zaman kültürle değişmeyen bir gösterimle sonuçlanır - bu yanıta bakın .

[2] Dikkate değer geçersiz kılmalar:

  • Koleksiyonların daha önce tartışılan dizilişi ( benzeri bir şeyden ziyade boşlukla ayrılmış öğeler listesi System.Object[]).
  • Örneklerin hashtable benzeri gösterimi [pscustomobject]( burada açıklanmıştır ), boş dizeden ziyade .
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.