J'ai le code suivant:
$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;
Lorsque j'essaie d'utiliser l'une des propriétés dans une commande d'exécution de chaîne:
& "$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'"
Il essaie d'utiliser simplement la valeur de $DatabaseSettings
plutôt que la valeur de $DatabaseSettings[0].DatabaseName
, ce qui n'est pas valide.
Ma solution de contournement consiste à le copier dans une nouvelle variable.
Comment puis-je accéder à la propriété de l'objet directement dans une chaîne entre guillemets?
la source
@Joey a la bonne réponse, mais juste pour ajouter un peu plus pourquoi vous devez forcer l'évaluation avec
$()
:Votre exemple de code contient une ambiguïté qui indique pourquoi les fabricants de PowerShell ont peut-être choisi de limiter l'expansion à de simples références de variables et de ne pas prendre en charge également l'accès aux propriétés (en passant: l'expansion de la chaîne se fait en appelant la
ToString()
méthode sur l'objet, ce qui peut expliquer certains résultats «étranges»).Votre exemple contenu à la toute fin de la ligne de commande:
Si les propriétés des objets étaient développées par défaut, ce qui précède se résoudrait à
puisque l'objet référencé par
$LogFileName
n'aurait pas de propriété appeléeldf
,$null
(ou une chaîne vide) serait substituée à la variable.la source
@Joey a une bonne réponse. Il existe un autre moyen avec un look plus .NET avec un équivalent String.Format, je le préfère lors de l'accès aux propriétés sur des objets:
Choses sur une voiture:
Créez un objet:
Interpoler une chaîne:
Les sorties:
la source
write-host "foo = {0}" -f $foo
car PowerShell le traitera-f
comme leForegroundColor
paramètre pourwrite-host
. Dans cet exemple, vous devezwrite-host ( "foo = {0}" -f $foo )
. Il s'agit d'un comportement PowerShell standard, mais il convient de le noter.String.Format
.Expression
contraireArgument
(jusqu'à un terminateur de commande).Note de documentation:
Get-Help about_Quoting_Rules
couvre l'interpolation de chaîne, mais, à partir de PSv5, pas en profondeur.Pour compléter la réponse utile de Joey avec un résumé pragmatique de l' extension de chaîne de PowerShell (interpolation de chaîne dans des chaînes entre guillemets (
"...")
y compris dans des chaînes ici entre guillemets ):Seules les références telles que
$foo
,$global:foo
(ou$script:foo
, ...) et$env:PATH
(variables d'environnement) sont reconnues lorsqu'elles sont directement incorporées dans une"..."
chaîne - c'est-à-dire que seule la référence de variable elle - même est développée, indépendamment de ce qui suit.Pour dissocier un nom de variable des caractères suivants de la chaîne, placez-le entre
{
et}
; par exemple${foo}
.Ceci est particulièrement important si l' on suit le nom de la variable par un
:
, comme PowerShell serait par ailleurs considérer tout entre$
et:
une portée spécificateur, ce qui provoque généralement l'interpolation à l' échec ; par exemple, des"$HOME: where the heart is."
pauses, mais"${HOME}: where the heart is."
fonctionne comme prévu.( En variante, les
`
caractères d' échappement du:
:"$HOME`: where the heart is."
).Pour traiter a
$
ou a"
comme un littéral , préfixez-le avec un caractère d' échappement.`
(un backtick ); par exemple:"`$HOME's value: `"$HOME`""
Pour toute autre chose, y compris l'utilisation d'indices de tableau et l'accès aux propriétés d' une variable d'objet , vous devez placer l'expression dans
$(...)
, l' opérateur de sous - expression (par exemple,"PS version: $($PSVersionTable.PSVersion)"
ou"1st el.: $($someArray[0])"
)$(...)
même vous permet d'incorporer la sortie de lignes de commande entières dans des chaînes entre guillemets (par exemple,"Today is $((Get-Date).ToString('d'))."
).Les résultats de l'interpolation ne ressemblent pas nécessairement au format de sortie par défaut (ce que vous verriez si vous imprimiez la variable / sous-expression directement dans la console, par exemple, ce qui implique le formateur par défaut; voir
Get-Help about_format.ps1xml
):Les collections , y compris les tableaux, sont converties en chaînes en plaçant un seul espace entre les représentations sous forme de chaîne des éléments (par défaut; un séparateur différent peut être spécifié en définissant
$OFS
) Par exemple, les"array: $(@(1, 2, 3))"
rendementsarray: 1 2 3
Les cas de tout autre type (y compris les éléments des collections qui ne sont pas des collections elles - mêmes) sont de chaîne de caractères par soit appeler la
IFormattable.ToString()
méthode avec la culture invariante , si le type de l'instance prend en charge l'IFormattable
interface de [1] , ou en appelant.psobject.ToString()
, qui dans la plupart des cas simplement invoque la.ToString()
méthode du type .NET sous-jacent [2] , qui peut ou non donner une représentation significative: à moins qu'un type (non primitif) n'ait spécifiquement remplacé la.ToString()
méthode, tout ce que vous obtiendrez est le nom complet du type (par exemple, les"hashtable: $(@{ key = 'value' })"
rendementshashtable: System.Collections.Hashtable
).Pour obtenir le même résultat que dans la console , utilisez une sous-expression et un tube vers
Out-String
et appliquez.Trim()
pour supprimer toutes les lignes vides de début et de fin, si vous le souhaitez; par exemple,"hashtable:`n$((@{ key = 'value' } | Out-String).Trim())"
donne:[1] Ce comportement peut-être surprenant signifie que, pour les types qui prennent en charge les représentations sensibles à la culture,
$obj.ToString()
donne une représentation courante appropriée"$obj"
à la culture , alors que (interpolation de chaîne) aboutit toujours à une représentation invariante de la culture - voir ma réponse .[2]
Remplacements notables: * La stringification des collections évoquée précédemment (liste d'éléments séparés par des espaces plutôt que quelque chose comme
System.Object[]
).* La représentation des instances de type table de hachage
[pscustomobject]
(expliquée ici ) plutôt que la chaîne vide .la source