扩展文件内容中的变量

时间:2009-11-03 12:24:31

标签: powershell variables

我有一个文件template.txt,其中包含以下内容:

Hello ${something}

我想创建一个PowerShell脚本来读取文件并扩展模板中的变量,即

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

我怎么能这样做?

3 个答案:

答案 0 :(得分:29)

另一种选择是使用ExpandString(),例如:

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

Invoke-Expression也可以。不过要小心。这两个选项都能够执行任意代码,例如:

# 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

如果你想拥有一个“安全”的字符串eval而不会意外地运行代码,那么你可以将PowerShell作业和受限制的运行空间组合在一起,例如:

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

现在,如果您尝试在使用cmdlet的字符串中使用表达式,则不会执行该命令:

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

如果您希望在尝试命令时看到失败,请使用$ ExecutionContext.InvokeCommand.ExpandString扩展$ str参数。

答案 1 :(得分:5)

我找到了这个解决方案:

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

答案 2 :(得分:0)

由于我真的不喜欢“要记住的事”的想法-在这种情况下,请记住PS将评估变量并运行模板中包含的任何命令-我找到了另一种方法。

代替模板文件中的变量,而是创建自己的令牌-如果您不处理HTML,则可以使用例如<variable>,如下:

Hello <something>

基本上使用任何唯一的令牌。

然后在您的PS脚本中,使用:

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

它比简单的InvokeCommand麻烦,但是比设置有限的执行环境更清晰,只是为了避免处理简单模板时的安全风险。 YMMV取决于要求:-)