2009-11-03 12 views
25

ich eine Datei template.txt haben, die Folgendes enthält:Expanding Variablen in Dateiinhalte

Hello ${something} 

Ich mag würde ein Powershell-Skript erstellen, das die Datei liest und erweitert die Variablen in der Vorlage, dh

$something = "World" 
$template = Get-Content template.txt 
# replace $something in template file with current value 
# of variable in script -> get Hello World 

Wie könnte ich das tun?

+0

Große Frage! Ich musste nur herausfinden, wie ich das Gleiche machen kann. – Noldorin

+1

Nur um einen Kommentar zu einer Antwort unten zu wiederholen, ich kenne keine Möglichkeit, dies zu tun (variable Erweiterung), die nicht erlaubt, dass beliebige Ausdrücke ausgeführt werden. Ich gab Powershell-Variablen auf und verwendete stattdessen Umgebungsvariablen mit '[System.Environment] :: ExpandEnvironmentVariables()'. Jede ** sichere ** Lösung mit Powershell-Variablen wäre sehr interessant! – Tao

Antwort

26

Eine weitere Option ist ExpandString() z.B .:

$expanded = $ExecutionContext.InvokeCommand.ExpandString($template) 

Invoke-Expression auch arbeiten zu verwenden. Aber sei vorsichtig. Beide Optionen sind in der Lage die Ausführung beliebigen Codes zB:

# Contents of file template.txt 
"EvilString";$(remove-item -whatif c:\ -r -force -confirm:$false -ea 0) 

$template = gc template.txt 
iex $template # could result in a bad day 

Wenn Sie einen „sicheren“ string eval ohne das Potenzial haben wollen, versehentlich Code ausführen, dann können Sie Powershell-Arbeitsplätze und beschränkt Runspaces kombinieren, um genau das zu tun zB:

PS> $InitSB = {$ExecutionContext.SessionState.Applications.Clear(); $ExecutionContext.SessionState.Scripts.Clear(); Get-Command | %{$_.Visibility = 'Private'}} 
PS> $SafeStringEvalSB = {param($str) $str} 
PS> $job = Start-Job -Init $InitSB -ScriptBlock $SafeStringEvalSB -ArgumentList '$foo (Notepad.exe) bar' 
PS> Wait-Job $job > $null 
PS> Receive-Job $job 
$foo (Notepad.exe) bar 

Nun, wenn Sie einen Ausdruck in der Zeichenfolge zu verwenden versuchen, ein Cmdlet verwendet, wird dies den Befehl nicht ausführen:

PS> $job = Start-Job -Init $InitSB -ScriptBlock $SafeStringEvalSB -ArgumentList '$foo $(Start-Process Notepad.exe) bar' 
PS> Wait-Job $job > $null 
PS> Receive-Job $job 
$foo $(Start-Process Notepad.exe) bar 

wenn Sie WO Möchten Sie einen Fehler sehen, wenn ein Befehl versucht wird, verwenden Sie $ ExecutionContext.InvokeCommand.ExpandString, um den $ str-Parameter zu erweitern.

+0

Das ist perfekt, danke! –

+0

Tut mir leid, wenn ich etwas missverstanden habe, aber soweit ich das sagen kann, ist 'ExpandString()' überhaupt nicht sicherer ... Es führt immer noch eine Ausdruckserweiterung durch, was bedeutet, dass in Ihrem Beispiel alles in C: \ noch kommt gelöscht! Wollten Sie angeben, dass auch mit 'ExpandString()' beliebiger Code ** ** ausgeführt wird? – Tao

+0

(im Beispiel oben, '$ ExecutionContext.InvokeCommand.ExpandString ($ template)' ergibt einen ebenso schlechten Tag!) – Tao

5

Ich habe diese Lösung gefunden:

$something = "World" 
$template = Get-Content template.txt 
$expanded = Invoke-Expression "`"$template`"" 
$expanded 
+2

Könnte Sie in Schwierigkeiten bringen, wenn Code in der Datei vorhanden ist. –