I have a file template.txt
which contains the following:
Hello ${something}
I would like to create a PowerShell script that reads the file and expands the variables in the template, i.e.
$something = "World"
$template = Get-Content template.txt
# replace $something in template file with current value
# of variable in script -> get Hello World
How could I do this?
Variable expansion is the term used for the ability to access and manipulate values of variables and parameters. Basic expansion is done by preceding the variable or parameter name with the $ character. This provides access to the value.
Just use double quotes instead of single quotes. You'll also need to use {} to delimit the number_line variable correctly and escape the \ , too.
Bash uses the value formed by expanding the rest of parameter as the new parameter ; this is then expanded and that value is used in the rest of the expansion, rather than the expansion of the original parameter . This is known as indirect expansion .
Most programs separate their command line arguments with a space. But the PATH environment variable doesn't use spaces to separate directories. It uses semicolons.
Another option is to use ExpandString() e.g.:
$expanded = $ExecutionContext.InvokeCommand.ExpandString($template)
Invoke-Expression will also work. However be careful. Both of these options are capable of executing arbitrary code e.g.:
# 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
If you want to have a "safe" string eval without the potential to accidentally run code then you can combine PowerShell jobs and restricted runspaces to do just that e.g.:
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
Now if you attempt to use an expression in the string that uses a cmdlet, this will not execute the command:
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
If you would like to see a failure if a command is attempted, then use $ExecutionContext.InvokeCommand.ExpandString to expand the $str parameter.
I've found this solution:
$something = "World"
$template = Get-Content template.txt
$expanded = Invoke-Expression "`"$template`""
$expanded
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With