Count属性如何在Powershell中运行?

时间:2014-10-22 09:41:45

标签: powershell

我做了一个非常不幸的错字,花了我相当宝贵的时间:

$errors.Count

即使存在错误,也会返回“0”,因为变量名称应为 singular 工作:

$error.clear()                # To ensure a correct repro
Copy-Item asdf fdsa           # Will show an error
$error.Count                  # Will output "1"

但是,我现在想知道为什么$errors.Count给了我任何,以及为什么它给了我“0”。所以我接着做了一些测试,得到了以下结果:

$asdf.Count                   # Will output "0"
$nrOfEinsteinsInSpace.Count   # Will output "0"
$a = 0; $a.Count;             # Will output "1"
$b = 2; $a.Count;             # Will output "1"
$x = 1,2,3; $x.Count;         # Will output "3"

收集更多数据以便能够在这里提出一个明智的问题:

$true.Count                   # Will output "1"
$false.Count                  # Will output "1"

所以我们有以下不同的情况:

  1. 数组(类似)变量,其中.Count将输出项目数。
  2. 不存在的变量,其中.Count将输出“0”。
  3. 声明的变量,其中.Count将输出“1”。
  4. 内置变量,其中.Count将输出“1”。
  5. 案例2,3和4对我没有任何意义(还)。这里发生了什么?这记录在哪里? .Count属性如何工作?

3 个答案:

答案 0 :(得分:15)

从PowerShell V3开始,属性Count和Length接收到与扩展类型数据(也称为ETS或扩展类型系统)无关的非常特殊的处理。

如果实例具有Count / Length属性,那么一切都像在V1 / V2中那样继续工作 - 返回实例的值。

如果实例没有Count / Length属性,从V3开始,而不是那个是错误,你就会回来1.如果实例是$ null,你将会回来0.如果你打开了严格模式,你将收到类似于V2的错误。

我承认这有点奇怪,但它解决了cmdlet返回0,1或多个对象时的常见问题。

通常,您将通过管道或foreach语句迭代这些结果。例如:

dir nosuchfile* | % { $_ }
foreach ($item in dir nosuchfile*) { $_ }

在上面的foreach案例中,如果命令没有返回任何值,V2实际上会进入循环。这在V3中已经改变,以更好地满足人们的期望,但这也意味着:

foreach ($item in $null) { $_ }

也永远不会进入循环。

for语句是迭代结果的另一种方式,例如

$results = dir nosuchfile*
for ($i = 0; $i -lt $results.Count; $i++) { $results[$i] }

在这个例子中,$ result中有多少个对象并不重要,循环工作得很好。请注意,在V1 / V2中,您可以写:

$results = @(dir nosuchfile*)

这确保了$ results是一个数组,但是这种语法很难看,许多人都会忘记它,因此更改为以更宽容的方式支持Count / Length。

答案 1 :(得分:5)

为了补充保罗的答案,这可能与extended type data有关。引用文档的相关部分:

  

扩展类型数据定义了其他属性和方法   Windows PowerShell中对象类型的(“成员”)。你可以扩展任何   Windows PowerShell支持的类型并使用添加的   属性和方法与使用属性的方式相同   在对象类型上定义的。

  

Windows PowerShell中有三种扩展类型数据源   会话。   Windows PowerShell安装目录中的Types.ps1xml文件会自动加载到每个Windows PowerShell会话中。

如果你打开那个Types.ps1xml文件(在$pshome中),你会在文件的开头看到这个:

   <Type>
        <Name>System.Array</Name>
        <Members>
            <AliasProperty>
                <Name>Count</Name>
                <ReferencedMemberName>Length</ReferencedMemberName>
            </AliasProperty>
        </Members>
    </Type>

所以我的猜测是,通过提供“.Count”属性,PowerShell假设这是一个数组。

答案 2 :(得分:3)

以下是我认为它的工作原理:

案例1:在数组中,.Count属性实际上链接到.Length属性,该属性显示数组中项目的数量

案例2:powershell自动创建非exitent变量,并使用值$null初始化

案例3/4:在这个问题上,我不确定它为什么会发生,但由于String和Int或boolean Objects都没有.Count属性,我可以想象该属性是由父对象继承的。

行为表明该变量被视为数组,因此分配1个值,输出将为1,没有值,结果将为0。

编辑: 为了完整起见,这里是文档链接:Technet,谢谢@David Brabant