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直接使用).
@( & { } ).Countyield 0(执行空脚本块输出"null collection"([System.Management.Automation.Internal.AutomationNull]::Value)
警告:@()在New-Object创建数组/集合的调用周围输出包含在单元素外部数组中的数组/集合.
@(New-Object System.Collections.ArrayList).Countyield 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 次 |
| 最近记录: |