PowerShell在双引号内插值时输出数组项
我在PowerShell中发现了一些围绕数组和双引号的奇怪行为。如果创建并打印数组中的第一个元素,例如:PowerShell在双引号内插值时输出数组项,powershell,string-interpolation,Powershell,String Interpolation,我在PowerShell中发现了一些围绕数组和双引号的奇怪行为。如果创建并打印数组中的第一个元素,例如: $test = @('testing') echo $test[0] Output: testing 一切正常。但如果我用双引号括起来: echo "$test[0]" Output: testing[0] 仅计算$test变量,数组标记[0]被视为字符串。简单的解决方法是避免在双引号中插入数组变量,或者先将它们分配给另一个变量。但是这种行为是设计的吗?因此,当您使用插值时,默认情况
$test = @('testing')
echo $test[0]
Output:
testing
一切正常。但如果我用双引号括起来:
echo "$test[0]"
Output:
testing[0]
仅计算$test变量,数组标记[0]被视为字符串。简单的解决方法是避免在双引号中插入数组变量,或者先将它们分配给另一个变量。但是这种行为是设计的吗?因此,当您使用插值时,默认情况下,它只对下一个变量进行整体插值。所以当你这样做的时候:
"$test[0]"
它将$test视为下一个变量,它意识到这是一个数组,它没有显示数组的好方法,因此它决定它不能插值,而只是将字符串显示为字符串。解决方案是显式告诉PowerShell要插值的位从何处开始,在何处停止:
"$($test[0])"
请注意,这种行为是我使用格式化字符串而不是依赖插值的主要原因之一:
"{0}" -f $test[0]
在这种情况下,您必须:
echo "$($test[0])"
另一种选择是使用字符串格式
echo "this is {0}" -f $test[0]
请注意,在访问字符串中的属性时也会出现这种情况。像“$a.Foo”
-应该写为“$($a.Foo)”
包含有效的解决方案,但仅粗略解释了PowerShell的字符串扩展(字符串插值):
- 只有变量本身可以直接嵌入双引号字符串(
)(相比之下,单引号字符串(“…”
)与许多其他语言一样,用于文本内容)“…”
- 这适用于正则变量和引用特定名称空间的变量;e、 g.:
,“var包含:$var”
“路径:$env:Path”
- 如果变量名称后的第一个字符可能会被误认为是名称的一部分,这主要包括
-使用变量名称周围的:
来消除歧义;e、 g.:{…}
,“${var}”
“${env:PATH}”
- 若要将
用作文本,必须使用PowerShell的转义字符$
对其进行转义;e、 g.:`
“变量`$var”
- 这适用于正则变量和引用特定名称空间的变量;e、 g.:
- 变量名后面的任何字符(包括
和[
都被视为字符串的文字部分,因此为了索引到嵌入变量(
)或访问属性($var[0]
),您需要$var.Count
,实际上,$(…)
允许您嵌入整个语句);例如:$(…)
“第一个元素:$($var[0])”
“元素计数:$($var.count)”
“今天的日期:$((获取日期-显示提示日期|输出字符串).Trim())”
- 字符串化(到字符串的转换)应用于任何尚未成为字符串的变量值/计算结果:
- 注意事项:如果可以应用特定于区域性的格式,PowerShell将选择不变区域性,这在很大程度上与美式英语日期和数字格式一致;也就是说,日期和数字将以美式格式表示(例如,月首日期格式和
作为小数点) - 本质上,对任何生成的非字符串对象或集合调用
方法(严格地说,它是.ToString()
,在某些情况下会覆盖.psobject.ToString()
,特别是对于数组/集合和PS自定义对象).ToString()
- 请注意,这与直接输出变量或表达式时得到的表示形式不同,许多类型没有有意义的默认字符串表示形式-它们只返回其完整类型名。
但是,您可以嵌入
,以便显式应用PowerShell的默认输出格式$(…| Out字符串)
- 有关严格化的更全面讨论,请参阅
- 请注意,这与直接输出变量或表达式时得到的表示形式不同,许多类型没有有意义的默认字符串表示形式-它们只返回其完整类型名。
- 注意事项:如果可以应用特定于区域性的格式,PowerShell将选择不变区域性,这在很大程度上与美式英语日期和数字格式一致;也就是说,日期和数字将以美式格式表示(例如,月首日期格式和
如上所述,使用
-f
,字符串格式运算符(-f,-f
运算符基于该运算符)
陷阱:-f
具有很高的可用性,因此一定要在(…)
中包含RHS表达式,而不是简单的索引或属性访问;例如,'{0:N2}'-f1/3
不会按预期工作,只有'{0:N2}'-f(1/3)
会工作
注意事项:字符串插值和-f
之间存在重要差异
:
- 与
内部的扩展不同,“…”
运算符对区域性敏感:-f
PS> $arr = 1, 2, 3; "`$arr: $arr"; '$arr: {0}' -f (, $arr) $arr: 1 2 3 $arr: System.Object[]
- 因此,以下两个看似等价的语句并不适用
产生相同的结果:
PS> [cultureinfo]::CurrentCulture='fr'; $n=1.2; "expanded: $n"; '-f: {0}' -f $n expanded: 1.2 -f: 1,2
- 请注意,只有
格式的命令才尊重法语(-f
)小数点(fr
)。,
再次,请参阅,以全面了解PowerShell何时对文化敏感,何时不敏感
- 因此,以下两个看似等价的语句并不适用
产生相同的结果:
- 与
内部的扩展不同,“…”
将数组字符串化为-f
:[]
PS> $arr = 1, 2, 3; "`$arr: $arr"; '$arr: {0}' -f (, $arr) $arr: 1 2 3 $arr: System.Object[]
- 请注意,
插值如何创建所有数组元素字符串化的空格分隔列表,而“…”
-formatting仅打印数组的类型名称。-f
(如前所述,
内部的$arr
相当于:“…”
,提供友好表示的通常是不可见的助手类型(1,2,3).psobject.ToString()
。)[psobject]
- 还要注意
- 请注意,