上次我对PowerShell急切展开集合的方式感到困惑时,Keith 总结了它的启发式如下:
将结果(数组)放在分组表达式(或子表达式,例如 $())中使其再次符合展开的条件。
我已经把这个建议铭记在心,但仍然发现自己无法解释一些深奥的东西。特别是, Format 运算符似乎不遵守规则。
$lhs = "{0} {1}"
filter Identity { $_ }
filter Square { ($_, $_) }
filter Wrap { (,$_) }
filter SquareAndWrap { (,($_, $_)) }
$rhs = "a" | Square
# 1. all succeed
$lhs -f $rhs
$lhs -f ($rhs)
$lhs -f $($rhs)
$lhs -f @($rhs)
$rhs = "a" | Square | Wrap
# 2. all succeed
$lhs -f $rhs
$lhs -f ($rhs)
$lhs -f $($rhs)
$lhs -f @($rhs)
$rhs = "a" | SquareAndWrap
# 3. all succeed
$lhs -f $rhs
$lhs -f ($rhs)
$lhs -f $($rhs)
$lhs -f @($rhs)
$rhs = "a", "b" | SquareAndWrap
# 4. all succeed by coercing the inner array to the string "System.Object[]"
$lhs -f $rhs
$lhs -f ($rhs)
$lhs -f $($rhs)
$lhs -f @($rhs)
"a" | Square | % {
# 5. all fail
$lhs -f $_
$lhs -f ($_)
$lhs -f @($_)
$lhs -f $($_)
}
"a", "b" | Square | % {
# 6. all fail
$lhs -f $_
$lhs -f ($_)
$lhs -f @($_)
$lhs -f $($_)
}
"a" | Square | Wrap | % {
# 7. all fail
$lhs -f $_
$lhs -f ($_)
$lhs -f @($_)
$lhs -f $($_)
}
"a", "b" | Square | Wrap | % {
# 8. all fail
$lhs -f $_
$lhs -f ($_)
$lhs -f @($_)
$lhs -f $($_)
}
"a" | SquareAndWrap | % {
# 9. only @() and $() succeed
$lhs -f $_
$lhs -f ($_)
$lhs -f @($_)
$lhs -f $($_)
}
"a", "b" | SquareAndWrap | % {
# 10. only $() succeeds
$lhs -f $_
$lhs -f ($_)
$lhs -f @($_)
$lhs -f $($_)
}
应用我们在上一个问题中看到的相同模式,很明显为什么像 #1 和 #5 这样的情况表现不同:管道运算符向脚本引擎发出信号以展开另一个级别,而赋值运算符没有。换句话说,位于两个 | 之间的所有内容都被视为一个分组表达式,就好像它在 () 中一样。
# all of these output 2
("a" | Square).count # explicitly grouped
("a" | Square | measure).count # grouped by pipes
("a" | Square | Identity).count # pipe + ()
("a" | Square | Identity | measure).count # pipe + pipe
出于同样的原因,案例#7 与#5 相比没有任何改进。任何添加额外Wrap的尝试都将立即被额外的管道破坏。同上 #8 与 #6。有点令人沮丧,但我完全同意这一点。
剩下的问题:
- 为什么案例#3 没有遭受与#4 相同的命运? $rhs应该保存嵌套数组(,("a", "a"))但它的外层正在展开......某处......
- #9-10 中的各种分组运算符是怎么回事?为什么他们的行为如此不规律,为什么需要他们?
- 为什么 #10 的失败不会像 #4 那样优雅地降级?