2009-11-03 9 views
25

Mam plik template.txt który zawiera następujące elementy:Rozszerzenie zmiennych w zawartości plików

Hello ${something} 

Chciałbym utworzyć skrypt PowerShell, który odczytuje plik i rozszerza zmiennych w szablonie, czyli

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

Jak mogę to zrobić?

+0

Świetne pytanie! Po prostu musiałem wymyślić, jak zrobić to samo. – Noldorin

+1

Tylko powtórzyć komentarz na odpowiedź poniżej, nie wiem sposób to zrobić (zmienne rozszerzenie), który nie pozwala na wykonywanie wyrażeń arbitralnych. Zrezygnowałem ze zmiennych powershell i wykorzystałem zmienne środowiskowe za pomocą '[System.Environment] :: ExpandEnvironmentVariables()'. Dowolne ** bezpieczne ** rozwiązanie wykorzystujące zmienne powershell byłoby bardzo interesujące! – Tao

Odpowiedz

26

Inną opcją jest użycie ExpandString() np .:

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

Invoke-Expression będzie również działać. Bądź jednak ostrożny. Obie te opcje są zdolne do wykonywania dowolnego kodu np

# 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 

Jeśli chcesz mieć „bezpieczne” eval ciąg bez potencjału do przypadkowego uruchomienia kodu następnie można połączyć pracę PowerShell i ograniczony runspaces właśnie do tego np:

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 

teraz jeśli spróbujesz użyć wyrażenia w ciąg, który korzysta z apletu polecenia, to nie wykona polecenia:

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 

Jeśli wo Lubimy widzieć awarię, jeśli polecenie jest wykonywane, a następnie użyj $ ExecutionContext.InvokeCommand.ExpandString, aby rozwinąć parametr $ str.

+0

To idealne, dzięki! –

+0

Przepraszam, jeśli coś nie rozumiem, ale o ile mogę powiedzieć, że 'ExpandString()' nie jest wcale bezpieczniejszy ... Nadal rozwija ekspresję, co oznacza w twoim przykładzie, dokładnie, wszystko w C: \ nadal dostaje usunięte! Czy chciałeś wskazać, że nawet z 'ExpandString()' dowolny kod ** również zostanie ** wykonany? – Tao

+0

(w powyższym przykładzie '$ ExecutionContext.InvokeCommand.ExpandString ($ template)' powoduje równie zły dzień!) – Tao

5

Znalazłem takie rozwiązanie:

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

Mógłbyś mieć kłopoty, jeśli w pliku był kod. –

Powiązane problemy