在powershell脚本块中向数组添加元素将数组转换为字符串
Adding element to array in powershell scriptblock converts array to string
我注意到在脚本块中使用数组有奇怪的行为。以下代码显示了问题:
$array = @("x", "y")
Write-Host "$($array.GetType().Name)"
Write-Host "$($array.GetType().BaseType)"
$bad = {
$array += "z"
Write-Host "$($array.GetType().Name)"
Write-Host "$($array.GetType().BaseType)"
$array
}
$good = {
$array = $array.Clone()
$array += "z"
Write-Host "$($array.GetType().Name)"
Write-Host "$($array.GetType().BaseType)"
$array
}
& $good
& $bad
执行脚本将产生以下输出:
Object[]
array
Object[]
array
x
y
z
String
System.Object
z
脚本块 $bad
没有像我预期的那样工作。它将数组转换为字符串,但它应该只是将元素 z
添加到数组中。如果没有添加元素,数组可以正常使用
我在 powershell 5.0 和 5.1 中注意到了这种行为,但在 ISE 中没有。这是一个错误还是有人可以解释一下?
这是范围问题。 scriptblocks中赋值操作左边的变量是在局部作用域中定义的。
此声明
$array = $array.Clone()
克隆 global 变量 $array
的值并将其分配给 local 变量 $array
(名称相同,但由于作用域不同而变量不同)。局部变量 $array
然后包含原始数组的副本,因此下一条语句
$array += "z"
向该数组追加一个新元素。
在您的其他脚本块中,您立即将一个字符串附加到(本地)变量 $array
。在这种情况下,局部变量为空,因此 $array += "z"
与 $array = "z"
具有相同的效果,留下一个仅包含字符串 "z".
的变量
指定正确的范围,您将获得预期的行为:
$array = @("x", "y")
$not_bad = {
$script:array += "z"
Write-Host "$($script:array.GetType().Name)"
Write-Host "$($script:array.GetType().BaseType)"
$script:array
}
& $not_bad
但是请注意,这实际上会修改 global/script 范围内的原始数组(您的 $good
示例保持原始数组不变)。
我不确定我是否会将此行为视为错误,但它绝对是一个问题。
我想 post 我的首选解决方案,它基于 Ansgars 的解释:
$array = @("x", "y")
$not_bad = {
$array = $array + "z"
Write-Host "$($array.GetType().Name)"
Write-Host "$($array.GetType().BaseType)"
$array
}
& $not_bad
重要的是在添加更多元素之前分配给局部变量(或更好地创建局部变量)。一个简单的
$array = $array
可以,但这一行可能会造成混淆。
我注意到在脚本块中使用数组有奇怪的行为。以下代码显示了问题:
$array = @("x", "y")
Write-Host "$($array.GetType().Name)"
Write-Host "$($array.GetType().BaseType)"
$bad = {
$array += "z"
Write-Host "$($array.GetType().Name)"
Write-Host "$($array.GetType().BaseType)"
$array
}
$good = {
$array = $array.Clone()
$array += "z"
Write-Host "$($array.GetType().Name)"
Write-Host "$($array.GetType().BaseType)"
$array
}
& $good
& $bad
执行脚本将产生以下输出:
Object[]
array
Object[]
array
x
y
z
String
System.Object
z
脚本块 $bad
没有像我预期的那样工作。它将数组转换为字符串,但它应该只是将元素 z
添加到数组中。如果没有添加元素,数组可以正常使用
我在 powershell 5.0 和 5.1 中注意到了这种行为,但在 ISE 中没有。这是一个错误还是有人可以解释一下?
这是范围问题。 scriptblocks中赋值操作左边的变量是在局部作用域中定义的。
此声明
$array = $array.Clone()
克隆 global 变量 $array
的值并将其分配给 local 变量 $array
(名称相同,但由于作用域不同而变量不同)。局部变量 $array
然后包含原始数组的副本,因此下一条语句
$array += "z"
向该数组追加一个新元素。
在您的其他脚本块中,您立即将一个字符串附加到(本地)变量 $array
。在这种情况下,局部变量为空,因此 $array += "z"
与 $array = "z"
具有相同的效果,留下一个仅包含字符串 "z".
指定正确的范围,您将获得预期的行为:
$array = @("x", "y")
$not_bad = {
$script:array += "z"
Write-Host "$($script:array.GetType().Name)"
Write-Host "$($script:array.GetType().BaseType)"
$script:array
}
& $not_bad
但是请注意,这实际上会修改 global/script 范围内的原始数组(您的 $good
示例保持原始数组不变)。
我不确定我是否会将此行为视为错误,但它绝对是一个问题。
我想 post 我的首选解决方案,它基于 Ansgars 的解释:
$array = @("x", "y")
$not_bad = {
$array = $array + "z"
Write-Host "$($array.GetType().Name)"
Write-Host "$($array.GetType().BaseType)"
$array
}
& $not_bad
重要的是在添加更多元素之前分配给局部变量(或更好地创建局部变量)。一个简单的
$array = $array
可以,但这一行可能会造成混淆。