繁体   English   中英

在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中却没有注意到。 是一个错误还是有人可以解释?

这是一个范围问题。 脚本块中赋值操作左侧的变量在本地范围内定义。

这个说法

$array = $array.Clone()

克隆全局变量$array的值,并将其分配给局部变量$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示例使原始数组保持不变)。

我不确定是否会将此行为视为错误,但这绝对是一个陷阱。

我想根据Ansgars的说明发布我的首选解决方案:

$array = @("x", "y")

$not_bad = {
    $array = $array + "z"
    Write-Host "$($array.GetType().Name)"
    Write-Host "$($array.GetType().BaseType)"
    $array
}

& $not_bad

重要的是在添加其他元素之前分配给局部变量(或者更好地创建局部变量)。 一个简单的

$array = $array

可以,但是这行可能会造成混淆。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM