Arrays 当直接从get content分配或检索数组时,为什么数组的行为会有所不同
有件事我不明白 定义变量时:Arrays 当直接从get content分配或检索数组时,为什么数组的行为会有所不同,arrays,powershell,formatting,Arrays,Powershell,Formatting,有件事我不明白 定义变量时: $v = [byte]2, [byte]3 并检查其类型: $v.getType().name $f.getType().name 我明白了 然后我格式化$v: '{0} {1}' -f $v 哪张照片 2 3 现在,如果我得到文件的前两个字节: $f = (get-content 'xyz.txt' -encoding byte -readCount 2 -totalCount 2) 并检查其类型: $v.getType().name $f.getT
$v = [byte]2, [byte]3
并检查其类型:
$v.getType().name
$f.getType().name
我明白了
然后我格式化$v
:
'{0} {1}' -f $v
哪张照片
2 3
现在,如果我得到文件的前两个字节:
$f = (get-content 'xyz.txt' -encoding byte -readCount 2 -totalCount 2)
并检查其类型:
$v.getType().name
$f.getType().name
我得到了与以前相同的类型:Object[]
但是,与$v
不同,我无法格式化$f
:
'{0} {1}' -f $f
我收到错误消息错误格式化字符串:索引(基于零)必须大于或等于零且小于的大小,尽管数组的长度为2:
$f.length
返回
2
我不明白这是为什么,请解释一下。- 行为应被视为
操作符中的错误;从v7.1开始出现,并在中报告;它不影响具有数组操作数的其他运算符,例如-f
或-split
-in
- 解决方法是将
强制转换为$f
,或者,如果可以创建数组的副本,[array]
:@($f)
@()
,-…-@($f)
-作为注释-是更简单的选项,但请注意,使用@()
涉及到克隆(创建数组的浅层副本),而在本例中的[array]
强制转换则没有
另一种方法是将[array]
强制转换应用为类型约束(通过将其放置在$f=…
赋值的左侧):
注:
- 在PowerShell[Core]v6+中,必须使用
代替-AsByteStream
-Encoding Byte
- 如果省略
,也可以避免该问题,但请注意,这会降低命令的性能,因为随后会逐个发出字节;也就是说,使用-ReadCount 2
会发出一个作为一个整体的2字节数组的单个对象,而只-ReadCount 2-TotalCount 2
会将单个字节逐个发送到管道,在这种情况下,PowerShell引擎本身会在-TotalCount 2
分配的数组[object[]中收集这些字节
- 请注意,在这种情况下,直接将
应用于命令-@()
-)将不起作用,因为@(获取内容…
,由于参数组合@()
,接收一个恰好是整个数组的单个输出对象,因此将该单个对象包装到另一个数组中。这将产生一个单元素数组,其元素是字节的原始2元素数组;有关-ReadCount 2-TotalCount 2
工作原理的更多信息,请参阅@(…)
背景信息: 问题是在
Get Content-ReadCount
返回的每个数组周围都有一个不可见的[psobject]
包装器(在本例中只有一个),这意外地导致传递给-f
的$f
数组无法被识别
请注意,PowerShell的其他基于阵列的运算符(如-in
和-replace
)不受影响
可以通过两种方式绕过包装器:
$f.psobject.BaseObject
- 转换到
,如顶部所示[array]
- 通常,cmdlet生成的输出对象与PowerShell代码生成的输出不同,通常具有不可见的
包装器;大多数情况下,它们都是良性的,因为PowerShell通常只关心被包装的.NET对象,而不关心包装器,但有时会出现问题,例如在本例中-有关问题的讨论以及它所体现的其他上下文,请参阅[psobject]
- 为了测试给定对象是否有
包装器,请使用[psobject]
;e、 g:-is[psobject]
$var=1
$var-is[psobject]#->$false
$var=写入输出1
$var-由于使用了cmdlet,因此为[psobject]#->$true。
#您还可以直接测试命令输出。
(写入输出1)-是否为[psobject]#->$true
'abc' > xyz.txt
[array] $f = (get-content 'xyz.txt' -encoding byte -readCount 2 -totalCount 2)
'{0} {1}' -f $f