我在PowerShell中发现了一些奇怪的行为,包括数组和双引号。如果我在数组中创建并打印第一个元素,例如:
$test = @('testing')
echo $test[0]
Output:
testing
一切正常。但如果我在它周围加上双引号:
echo "$test[0]"
Output:
testing[0]
仅评估了$ test变量,并且数组标记[0]被字面上视为字符串。简单的解决方法是避免在双引号中插入数组变量,或者首先将它们分配给另一个变量。但这是设计的行为吗?
答案 0 :(得分:19)
因此,当您使用插值时,默认情况下它只插入toto中的下一个变量。所以当你这样做时:
"$test[0]"
它将$ test视为下一个变量,它意识到这是一个数组并且没有好的方法来显示数组,所以它决定它不能插值并只是将字符串显示为字符串。解决方案是明确告诉PowerShell要插入的位在何处开始以及停止的位置:
"$($test[0])"
请注意,这种行为是我使用格式化字符串而不是依赖插值的主要原因之一:
"{0}" -f $test[0]
答案 1 :(得分:9)
在这种情况下你必须这样做:
echo "$($test[0])"
另一种方法是使用字符串格式
echo "this is {0}" -f $test[0]
请注意,当您访问字符串中的属性时也会出现这种情况。与"$a.Foo"
一样 - 应写为"$($a.Foo)"
答案 2 :(得分:3)
EBGreen's helpful answer包含有效的解决方案,但只有 PowerShell 字符串扩展的粗略解释(字符串插值):
只有变量本身可以直接嵌入直接双引号字符串("..."
)(相比之下)单引号字符串('...'
)与许多其他语言一样,用于 literal 内容)。
这适用于引用特定命名空间的常规变量和变量;例如: -
"var contains: $var"
,"Path: $env:PATH"
如果变量名后面的第一个字符可能会被误认为是名称的一部分 - 特别是:
- 使用{...}
要消除歧义的变量名称;例如: -
"${var}"
,"${env:PATH}"
要使用$
作为文字,您必须使用`
,PowerShell的转义字符转义它;例如: -
"Variable `$var"
变量名之后的任何字符 - 包括[
和.
被视为字符串的 literal 部分,因此为了索引嵌入变量($var[0]
)或访问属性($var.Count
),您需要{{1} ,子表达式运算符(事实上,$(...)
允许您嵌入整个语句);例如:
$(...)
"1st element: $($var[0])"
"Element count: $($var.Count)"
字符串化(到字符串转换)应用于任何不是字符串的变量值/评估结果:
"Today's date: $((Get-Date -DisplayHint Date | Out-String).Trim())"
作为小数点)。 本质上,.
方法在任何生成的非字符串对象或集合上被称为(严格来说,它是.ToString()
,它会覆盖.psobject.ToString()
1}}在某些情况下,特别是对于数组/集合和PS自定义对象)
.ToString()
以显式应用PowerShell的默认输出格式。有关字符串化的更全面的讨论,请参阅我的this answer。
如前所述,使用 $(... | Out-String)
,字符串格式化运算符(-f
)是替代,用于字符串插值,用于分隔文字部分来自变量部分的字符串:
<format-string> -f <arg>[, ...]
请注意在LHS上使用'1st element: {0}; count: {1:x}' -f $var[0], $var.Count
,因为格式字符串(模板)本身就是文字。在这种情况下使用'...'
是一个很好的习惯,既可以表示使用文字内容的意图,又可以嵌入'...'
字符而无需转义。
除了简单的位置占位符(第一个参数为$
。第二个为{0}
,...),您可以选择多运行< strong>格式化对字符串转换的控制;在上面的示例中,{1}
请求数字的十六进制表示
有关可用格式,请参阅x
运算符所基于的.NET框架String.Format
method的文档。
陷阱:-f
具有较高的precedence,因此请确保在-f
中包含除简单索引或属性访问之外的RHS表达式;例如,(...)
无法按预期工作,只会'{0:N2}' -f 1/3
。
警告:字符串插值与'{0:N2}' -f (1/3)
之间存在重要差异:
与-f
内的扩展不同,"..."
运算符 对文化敏感:
因此,以下两个看似等效的语句不 产生相同的结果:
-f
请注意,只有PS> [cultureinfo]::CurrentCulture='fr'; $n=1.2; "expanded: $n"; '-f: {0}' -f $n
expanded: 1.2
-f: 1,2
格式的命令才会尊重法语(-f
)小数点(fr
)。
再次,请参阅previously linked answer,全面了解PowerShell何时不具备文化敏感性。
与,
内的扩展不同,"..."
将数组字符串化为-f
:
<type-name>[]
请注意PS> $arr = 1, 2, 3; "`$arr: $arr"; '$arr: {0}' -f (, $arr)
$arr: 1 2 3
$arr: System.Object[]
插值如何创建所有数组元素的字符串化的空格分隔列表,而"..."
- 格式化仅打印数组的类型名称。
(如上所述,-f
内的$arr
相当于:
"..."
并且通常不可见的助手类型(1, 2, 3).psobject.ToString()
提供友好的表示。)
另请注意[psobject]
如何在帮助器数组中包装数组(, ...)
,以确保$arr
将表达式视为单个操作数 ;默认情况下,数组的元素将被视为个别操作数。