Cob*_*ode 6 arrays powershell cmdlets scalar cim
我试图执行一些简单的if语句,但所有基于[Microsoft.Management.Infrastructure.CimInstance]的新cmdlet似乎都没有公开.count方法?
$Disks = Get-Disk
$Disks.Count
Run Code Online (Sandbox Code Playgroud)
不归还任何东西.我发现我可以将它转换为[数组],这使得它返回一个.NET .count方法,如预期的那样.
[Array]$Disks = Get-Disk
$Disks.Count
Run Code Online (Sandbox Code Playgroud)
这可以直接将其作为以前cmdlet的数组投射:
(Get-Services).Count
Run Code Online (Sandbox Code Playgroud)
推荐的解决方法是什么?
一个不起作用的例子:
$PageDisk = Get-Disk | Where {($_.IsBoot -eq $False) -and ($_.IsSystem -eq $False)}
If ($PageDisk.Count -lt 1) {Write-Host "No suitable drives."; Continue}
Else If ($PageDisk.Count -gt 1) {Write-Host "Too many drives found, manually select it."}
Else If ($PageDisk.Count -eq 1) { Do X }
Run Code Online (Sandbox Code Playgroud)
选项A(演员阵容):
[Array]$PageDisk = Get-Disk | Where {($_.IsBoot -eq $False) -and ($_.IsSystem -eq $False)}
If ($PageDisk.Count -lt 1) {Write-Host "No suitable drives."; Continue}
Else If ($PageDisk.Count -gt 1) {Write-Host "Too many drives found, manually select it."}
Else If ($PageDisk.Count -eq 1) { Do X }
Run Code Online (Sandbox Code Playgroud)
选项B(使用数组索引):
$PageDisk = Get-Disk | Where {($_.IsBoot -eq $False) -and ($_.IsSystem -eq $False)}
If ($PageDisk[0] -eq $Null) {Write-Host "No suitable drives."; Continue}
Else If ($PageDisk[1] -ne $Null) {Write-Host "Too many drives found, manually select it."}
Else If (($PageDisk[0] -ne $Null) -and (PageDisk[1] -eq $Null)) { Do X }
Run Code Online (Sandbox Code Playgroud)
选项C(数组) - 感谢@PetSerAl:
$PageDisk = @(Get-Disk | Where {($_.IsBoot -eq $False) -and ($_.IsSystem -eq $False)})
If ($PageDisk.Count -lt 1) {Write-Host "No suitable drives."; Continue}
Else If ($PageDisk.Count -gt 1) {Write-Host "Too many drives found, manually select it."}
Else If ($PageDisk.Count -eq 1) { Do X }
Run Code Online (Sandbox Code Playgroud)
基于CIM的cmdlet不暴露.Count方法的原因是什么?建议的方法是什么?选项B对我来说似乎很复杂,很难阅读.选项A有效,但是不应该将PowerShell转换为数组吗?我是以完全错误的方式解决这个问题吗?
在PSv3 +中,通过统一处理标量和集合,任何对象 - 甚至$null
- 都应该有一个.Count
属性(除了$null
应该支持索引[0]
).
任何不支持上述内容的对象都应被视为错误.
例如,[pscustomobject]
不遵守这些规则的实例是已知错误.
由于我不知道所述错误是否与输出的[Microsoft.Management.Infrastructure.CimInstance#ROOT/Microsoft/Windows/Storage/MSFT_Disk]
实例有关Get-Disk
,并且由于Get-Disk
- 至少目前 - 仅在Windows PowerShell中可用,因此我建议您在uservoice.com上提交单独的错误.
数组子表达式运算符的使用@(...)
是唯一必要的:
作为上述错误的解决方法.
如果标量对象碰巧有自己的 .Count
属性.
通常,如果你确实需要确保某些东西是一个数组,那么使用@(...)
而不是[Array] ...
/[object[]] ...
- @()
是PowerShell惯用的,更简洁,语法更容易.
也就是说,鉴于@()
技术上创建了现有数组的(浅)副本,您可能更喜欢[Array]
处理可能较大的数组.
此外,@(...)
并且[Array] ...
通常不等同,因为PetSerAl在对该问题的评论中提供了有用的示例; 适应他的一个例子:
@($null)
返回单项数组,其唯一元素是$null
,[Array] $null
但没有效果(停留$null
).
这种行为@()
与其目的一致(见下文):因为$null
它不是一个数组,所以@()
将它包装在一个中(导致一个[System.Object[]]
实例$null
作为唯一的元素).
在PetSerAl的其他例子中,@()
使用New-Object
创建数组和集合的行为可能会令人惊讶 - 见下文.
@(...)
和工作方式:松散地说,array-subexpression运算符的目的@()
是确保表达式/命令的结果被视为数组,即使它恰好是标量(单个对象).
更准确地说,@()
表现如下:给PetSerAl的帽子提示他的广泛帮助.
在PSv5.1 +,使用一个表达式直接构建的阵列使用,
(数组表达式运算符)优化@()
程:
例如,@(1, 2)
与刚刚相同1, 2
,并且@(, 1)
与刚刚相同, 1
.
在使用just 构造的数组的情况下,
- 这会生成一个System.Object[]
数组 - 这种优化很有用,因为它节省了首次展开该数组然后重新打包它的不必要的步骤(见下文).
据推测,这种优化是由于@( ..., ..., ...)
构建阵列的广泛且以前效率低下的实践所促成的,源于构造阵列@()
所需的错误信念.
然而,在Windows PowerShell中仅V5.1的优化也构建阵列与一个应用时,特定类型的使用铸铁,如[int[]]
(行为在PowerShell中得到纠正核心及以上的Windows PowerShell版本不受影响); 例如,
@([int[]] (1, 2)).GetType().Name
收益率Int32[]
.这是其中唯一的情况@()
返回的东西其他比System.Object[]
,并假设它总是会导致意想不到的错误和副作用 ; 例如:
@([int[]] (1, 2))[-1] = 'foo'
休息.
$a = [int[]] (1, 2); $b = @([int[]] $a)
意外地没有创建新数组 - 请参阅此GitHub问题.
否则:如果内部的(第一个)语句@(...)
是表达式,则使用PowerShell的标准集合展开(展开)技术收集它; 但是,命令的输出被解释为原样; 在任何一种情况下,结果对象的数量决定了行为:
如果结果是单个项目/不包含任何项目,则结果将包装在单个元素/空数组中[System.Object[]]
.
例如,@('foo').GetType().Name
产量Object[]
和@('foo').Count
产量1
(尽管如上所述,在PSv3 +中,您可以'foo'.Count
直接使用).
@( & { } ).Count
yield 0
(执行空脚本块输出"null collection"([System.Management.Automation.Internal.AutomationNull]::Value
)
警告:@()
在New-Object
创建数组/集合的调用周围输出包含在单元素外部数组中的数组/集合.
@(New-Object System.Collections.ArrayList).Count
yield 1
- 空数组列表包含在单个元素System.Object[]
实例中.其原因是New-Object
,由于是一个命令(如小命令调用)是不受到展开,导致@()
只看到单个项(这恰好是一个数组/集合),因此,其它包装在单项目数组.
什么可能会产生混淆的是,这并没有当您使用的发生表达,因为表达的输出是构造一个数组/集合,展开(展开):
@([system.collections.arraylist]::new()).Count
产量0
; 表达式输出一个空集合,该集合将展开为不包含任何项目的结果,并@()
重新打包为空System.Object[]
数组.(...)
)与New-Object
-其将New-Object
命令到一个表达 -将产生相同的结果:@((New-Object System.Collections.ArrayList)).Count
产生0
太.如果结果包含多个项目,则这些项目将作为数组返回(通常,但在WinPSv5.1中并不总是 - 请参见上文)作为常规PowerShell数组([System.Object[]]
):
$arr = [int[]] (1, 2); @($arr)
展开[int[]]
数组$arr
,然后将元素重新打包为System.Object[]
数组.@()
,则实际上会得到一个[int[]]
数组.) 归档时间: |
|
查看次数: |
804 次 |
最近记录: |