Tengo el siguiente código:
$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;
Cuando intento usar una de las propiedades en un comando de ejecución de cadena:
& "$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'"
Intenta usar simplemente el valor de en $DatabaseSettings
lugar del valor de $DatabaseSettings[0].DatabaseName
, que no es válido.
Mi solución es copiarlo en una nueva variable.
¿Cómo puedo acceder a la propiedad del objeto directamente en una cadena entre comillas dobles?
fuente
@Joey tiene la respuesta correcta, pero solo para agregar un poco más sobre por qué necesita forzar la evaluación con
$()
:Su código de ejemplo contiene una ambigüedad que indica por qué los creadores de PowerShell pueden haber optado por limitar la expansión a meras referencias variables y no admitir el acceso a las propiedades también (como nota al margen: la expansión de cadenas se realiza llamando al
ToString()
método en el objeto, que puede explicar algunos resultados "extraños").Su ejemplo contenido al final de la línea de comando:
Si las propiedades de los objetos se expandieran de forma predeterminada, lo anterior se resolvería como
ya que el objeto referenciado por
$LogFileName
no tendría una propiedad llamadaldf
,$null
(o una cadena vacía) se sustituirá por la variable.fuente
@Joey tiene una buena respuesta. Hay otra forma con un aspecto más .NET con un String.Format equivalente, lo prefiero al acceder a las propiedades de los objetos:
Cosas sobre un automóvil:
Crea un objeto:
Interpolar una cadena:
Salidas:
fuente
write-host "foo = {0}" -f $foo
ya que PowerShell lo tratará-f
como elForegroundColor
parámetro parawrite-host
. En este ejemplo, necesitaríawrite-host ( "foo = {0}" -f $foo )
. Este es el comportamiento estándar de PowerShell, pero vale la pena señalarlo.String.Format
.Expression
otro modoArgument
(hasta un terminador de comando).Nota de documentación:
Get-Help about_Quoting_Rules
cubre la interpolación de cadenas, pero, a partir de PSv5, no en profundidad.Para complementar la útil respuesta de Joey con un resumen pragmático de la expansión de cadenas de PowerShell (interpolación de cadenas en cadenas entre comillas dobles (
"...")
, incluso en cadenas aquí entre comillas dobles ):Solamente las referencias tales como
$foo
,$global:foo
(o$script:foo
, ...) y$env:PATH
(variables de entorno) se reconocen cuando directamente incrustado en una"..."
cadena - que es, sólo la referencia variable en sí se expande, con independencia de lo que sigue.Para eliminar la ambigüedad de un nombre de variable de los caracteres subsiguientes en la cadena, enciérrelo entre
{
y}
; ej${foo}
.Esto es especialmente importante si el nombre de la variable va seguido de una
:
, ya que PowerShell consideraría todo lo que se encuentra entre$
y el:
de un alcance especificador, normalmente causando la interpolación a fallar ; por ejemplo, se"$HOME: where the heart is."
rompe, pero"${HOME}: where the heart is."
funciona según lo previsto.(Alternativamente,
`
-Escape la:
:"$HOME`: where the heart is."
).Para tratar un
$
o a"
como un literal , antepóngalo con escape char.`
(una tilde ); p.ej:"`$HOME's value: `"$HOME`""
Para cualquier otra cosa, incluido el uso subíndices de matriz y el acceso a las propiedades de una variable de objeto , debe incluir la expresión en
$(...)
el operador de subexpresión (p. Ej.,"PS version: $($PSVersionTable.PSVersion)"
O"1st el.: $($someArray[0])"
)$(...)
even le permite incrustar la salida de líneas de comando completas en cadenas entre comillas dobles (por ejemplo,"Today is $((Get-Date).ToString('d'))."
).Los resultados de la interpolación no necesariamente tienen el mismo aspecto que el formato de salida predeterminado (lo que vería si imprimiera la variable / subexpresión directamente en la consola, por ejemplo, que involucra el formateador predeterminado; consulte
Get-Help about_format.ps1xml
):Colecciones , incluyendo matrices, se convierten en cadenas por la colocación de un único espacio entre las representaciones de cadena de los elementos (por defecto; un separador diferente puede ser especificado por el ajuste
$OFS
) por ejemplo,"array: $(@(1, 2, 3))"
los rendimientosarray: 1 2 3
Las instancias de cualquier otro tipo (incluyendo elementos de colecciones que no son en sí mismos colecciones) se stringified por ya sea llamando al
IFormattable.ToString()
método con la cultura invariante , si el tipo de la instancia soporta laIFormattable
interfaz de [1] , o llamando.psobject.ToString()
, que en la mayoría de los casos simplemente invoca el.ToString()
método del tipo .NET subyacente [2] , que puede o no dar una representación significativa: a menos que un tipo (no primitivo) haya anulado específicamente el.ToString()
método, todo lo que obtendrá es el nombre completo del tipo (por ejemplo,"hashtable: $(@{ key = 'value' })"
rendimientoshashtable: System.Collections.Hashtable
).Para obtener el mismo resultado que en la consola , use una subexpresión y una canalización
Out-String
y aplique.Trim()
para eliminar las líneas vacías iniciales y finales, si lo desea; por ejemplo,"hashtable:`n$((@{ key = 'value' } | Out-String).Trim())"
rinde:[1] Este comportamiento quizás sorprendente significa que, para los tipos que apoyan representaciones sensibles a la cultura,
$obj.ToString()
produce una representación apropiada a la cultura actual , mientras que"$obj"
(interpolación de cadenas) siempre da como resultado una representación invariante a la cultura - vea esta respuesta mía.[2]
Anulaciones notables: * La cadena de colecciones discutida anteriormente (lista de elementos separados por espacios en lugar de algo así
System.Object[]
).* La representación de instancias similar a una tabla hash
[pscustomobject]
(explicada aquí ) en lugar de la cadena vacía .fuente