Mam następujący kod:
$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;
Kiedy próbuję użyć jednej z właściwości w poleceniu wykonania ciągu:
& "$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'"
Próbuje po prostu użyć wartości $DatabaseSettings
zamiast wartości $DatabaseSettings[0].DatabaseName
, która jest nieprawidłowa.
Moje obejście polega na skopiowaniu go do nowej zmiennej.
Jak mogę uzyskać dostęp do właściwości obiektu bezpośrednio w ciągu znaków umieszczonych w podwójnych cudzysłowach?
źródło
@Joey ma poprawną odpowiedź, ale tylko trochę więcej wyjaśniając, dlaczego musisz wymusić ocenę za pomocą
$()
:Twój przykładowy kod zawiera niejednoznaczność, która wskazuje na to, dlaczego twórcy programu PowerShell mogli zdecydować się na ograniczenie interpretacji do zwykłych odwołań do zmiennych i nie obsługują również dostępu do właściwości (na marginesie: interpretacja ciągów jest wykonywana przez wywołanie
ToString()
metody na obiekcie, która może wyjaśnić niektóre „dziwne” wyniki).Twój przykład zawarty na samym końcu linii poleceń:
...\$LogFileName.ldf
Jeśli właściwości obiektów byłyby rozszerzone domyślnie, powyższe rozwiązałoby się do
Ponieważ obiekt odwołuje
$LogFileName
nie miałby właściwość o nazwieldf
,$null
(lub pusty ciąg) zostanie zastąpione zmiennej.źródło
@Joey ma dobrą odpowiedź. Jest inny sposób z wyglądem bardziej .NET z odpowiednikiem String.Format, wolę go podczas uzyskiwania dostępu do właściwości obiektów:
Rzeczy o samochodzie:
$properties = @{ 'color'='red'; 'type'='sedan'; 'package'='fully loaded'; }
Utwórz obiekt:
$car = New-Object -typename psobject -Property $properties
Interpolacja ciągu:
"The {0} car is a nice {1} that is {2}" -f $car.color, $car.type, $car.package
Wyjścia:
# The red car is a nice sedan that is fully loaded
źródło
write-host "foo = {0}" -f $foo
ponieważ PowerShell będzie traktował-f
jakoForegroundColor
parametr forwrite-host
. W tym przykładzie musiszwrite-host ( "foo = {0}" -f $foo )
. Jest to standardowe zachowanie programu PowerShell, ale warte odnotowania.String.Format
.Expression
innyArgument
(aż do terminatora polecenia).Uwaga dokumentacyjna:
Get-Help about_Quoting_Rules
obejmuje interpolację ciągów, ale od PSv5 nie jest dogłębna.W celu uzupełnienia użytecznej odpowiedzi Joey'a z pragmatycznego Podsumowując PowerShell w ekspansji smyczkową (interpolacja ciągu w podwójnej notowane ciągi (
"..."
vel spieniania strun ), w tym podwójnie cytowanych tu-strings ):Tylko odniesienia, takie jak
$foo
,$global:foo
(lub$script:foo
, ...) i$env:PATH
(zmienne środowiskowe) są rozpoznawane, gdy są bezpośrednio osadzone w"..."
ciągu - to znaczy, tylko samo odwołanie do zmiennej jest rozwijane, niezależnie od tego, co następuje.Aby oddzielić nazwę zmiennej od kolejnych znaków w ciągu, umieść ją w
{
i}
; np${foo}
.Jest to szczególnie ważne, jeśli po nazwie zmiennej występuje a
:
, ponieważ w przeciwnym razie program PowerShell uwzględniłby wszystko między specyfikatorem zakresu$
a:
a , co zwykle powoduje niepowodzenie interpolacji ; np. przerwy, ale działa zgodnie z przeznaczeniem. (Alternatywnie, -escape : )."$HOME: where the heart is."
"${HOME}: where the heart is."
`
:
"$HOME`: where the heart is."
Aby traktować a
$
lub a"
jako literał , należy poprzedzić go znakiem ucieczki.`
( backtick ); na przykład:"`$HOME's value: `"$HOME`""
W przypadku czegokolwiek innego, w tym używania indeksów tablicowych i uzyskiwania dostępu do właściwości zmiennej obiektu , należy umieścić wyrażenie w
$(...)
, operator podwyrażenia (np."PS version: $($PSVersionTable.PSVersion)"
Lub"1st el.: $($someArray[0])"
)$(...)
even pozwala na osadzenie danych wyjściowych z całych wierszy poleceń w podwójnych cudzysłowach (np"Today is $((Get-Date).ToString('d'))."
.).Wyniki interpolacji niekoniecznie wyglądają tak samo, jak domyślny format wyjściowy (co można zobaczyć, gdybyś na przykład wydrukował zmienną / podwyrażenie bezpośrednio na konsolę, która obejmuje domyślny program formatujący; zobacz
Get-Help about_format.ps1xml
):Kolekcje , w tym tablice, są konwertowane na ciągi poprzez umieszczenie pojedynczej spacji między reprezentacjami łańcuchowymi elementów (domyślnie; inny separator można określić przez ustawienie
$OFS
) Np."array: $(@(1, 2, 3))"
Dajearray: 1 2 3
Instancje innego rodzaju (w tym elementów kolekcji, które same nie są kolekcje) są stringified przez albo wywołanie
IFormattable.ToString()
metody z kultury niezmienny , jeśli typ instancji obsługuje tenIFormattable
interfejs [1] , lub przez wywołanie.psobject.ToString()
, co jest w wielu przypadkach po prostu wywołuje.ToString()
metoda [2] bazowego typu .NET , która może, ale nie musi, dawać sensowną reprezentację: chyba że typ (inny niż pierwotny) wyraźnie przesłonił.ToString()
metodę, wszystko, co otrzymasz, to pełna nazwa typu (np."hashtable: $(@{ key = 'value' })"
plonyhashtable: System.Collections.Hashtable
).Aby uzyskać te same dane wyjściowe, co w konsoli , użyj wyrażenia podrzędnego i potoku do
Out-String
i zastosuj,.Trim()
aby usunąć wszelkie początkowe i końcowe puste wiersze, jeśli to konieczne; np."hashtable:`n$((@{ key = 'value' } | Out-String).Trim())"
plony:[1] To być może zaskakujące zachowanie oznacza, że dla typów, które obsługują reprezentacje zależne od kultury,
$obj.ToString()
daje bieżącą reprezentację odpowiednią dla kultury , podczas gdy"$obj"
(interpolacja ciągów) zawsze powoduje reprezentację niezmienną kulturowo - zobacz tę odpowiedź .[2] Istotne zmiany:
System.Object[]
).[pscustomobject]
(wyjaśniona tutaj ) zamiast pustego ciągu .źródło