为了延迟字符串插值并按需执行,使用then-current值,您必须使用@987654326 @[1] 在作为 模板 的 单引号 字符串上:
function HelloWorld
{
Param ($Greeting, $Name)
$ExecutionContext.InvokeCommand.ExpandString($Greeting)
}
HelloWorld 'Hello, $Name!' 'World' # -> 'Hello, World!'
注意'Hello, $Name!' 如何被单引用以防止即时扩展(插值)。
还要注意HelloWorld 的调用方式,其参数用空格 分隔,而不是,,也没有(...)。
在 PowerShell 中,函数像命令行可执行文件一样调用 - foo arg1 arg2 - 不像 C# 方法 - foo(arg1, arg2) - 请参阅 Get-Help about_Parsing。
如果您不小心使用, 分隔参数,您将构造一个数组,函数将其视为单个 参数。
为帮助您避免意外使用方法语法,您可以使用 Set-StrictMode -Version 2 或更高版本,但请注意,这需要额外的严格性检查。
请注意,由于默认情况下 PowerShell 函数还会看到在父范围(所有祖先范围)中定义的变量,因此您可以简单地定义模板在调用范围中引用的任何变量,而不是声明单个参数,例如 $Name:
function HelloWorld
{
Param ($Greeting) # Pass the template only.
$ExecutionContext.InvokeCommand.ExpandString($Greeting)
}
$Name = 'World' # Define the variable(s) used in the template.
HelloWorld 'Hello, $Name!' # -> 'Hello, World!'
警告:PowerShell 字符串插值支持完整命令 - 例如,"Today is $(Get-Date)" - 所以除非您完全控制或信任模板字符串,否则此技术可以安全风险。
Ansgar Wiechers 通过 PowerShell 的 -f 运算符 和 索引占位符 ({0}, {1}, ...):
请注意,您不能再将 transformations 作为模板字符串的一部分应用于参数或在其中嵌入命令。
function HelloWorld
{
Param ($Greeting, $Name)
$Greeting -f $Name
}
HelloWorld 'Hello, {0}!' 'World' # -> 'Hello, World!'
陷阱:
-
PowerShell 的字符串扩展使用 invariant 文化,而 -f 运算符执行 文化敏感 格式(sn-p 需要 PSv3+):
$prev = [cultureinfo]::CurrentCulture
# Temporarily switch to culture with "," as the decimal mark
[cultureinfo]::CurrentCulture = 'fr-FR'
# string expansion: culture-invariant: decimal mark is always "."
$v=1.2; "$v"; # -> '1.2'
# -f operator: culture-sensitive: decimal mark is now ","
'{0}' -f $v # -> '1,2'
[cultureinfo]::CurrentCulture = $prev
-
PowerShell 的字符串扩展支持扩展 collections(数组) - 它将它们扩展为以空格分隔的列表 - 而 -f 运算符仅支持 scalars(单个值) :
$arr = 'one', 'two'
# string expansion: array is converted to space-separated list
"$var" # -> 'one two'
# -f operator: array elements are syntactically treated as separate values
# so only the *first* element replaces {0}
'{0}' -f $var # -> 'one'
# If you use a *nested* array to force treatment as a single array-argument,
# you get a meaningless representation (.ToString() called on the array)
'{0}' -f (, $var) # -> 'System.Object[]'
[1] 以更容易发现的方式呈现$ExecutionContext.InvokeCommand.ExpandString() 方法 的功能,即通过Expand-String cmdlet,是GitHub feature-request issue #11693.