PowerShell null无法通过管道传输

时间:2014-09-04 04:56:16

标签: powershell

因此,您学习使用PowerShell避免的第一个陷阱是这个foreach:

$null | foreach { "hello" }

将执行一次。然而,我试图向同事解释这个概念并发生以下事情:

PS> $a = 1..9 | ? {$_ -eq 10}
PS> $a | % { "hello" }
PS>

我试图了解以下情况,但$a似乎是$null,简单明了。

PS> $a = 1..9 | ? {$_ -eq 10}
PS> $a -eq $null
True
PS> $a.gettype()
You cannot call a method on a null-valued expression.
At line:1 char:1
+ $a.gettype()
+ ~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

PS> $a | gm
gm : No object has been specified to the get-member cmdlet.
At line:1 char:6
+ $a | gm
+      ~~
    + CategoryInfo          : CloseError: (:) [Get-Member], InvalidOperationException
    + FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMemberCommand

PS> $a | % { "hello" }
PS> $null | % { "hello" }
hello
PS> 

以某种方式存在两种不同的“类型”吗? $a真的是一个因某种原因而被我混淆的数组吗?

1 个答案:

答案 0 :(得分:2)

有关此事的一些历史 -

给定PS > $a = 1..9 | ? {$_ -eq 10}

Powershell 2.0行为

PS > $a | % { "hello" }
hello
PS > $null | % { "hello" }
hello

Powershell 3.0行为 - 当变量为null时“修复”该问题,但内置$ null仍然会迭代

PS > $a | % { "hello" }
PS > $null | % { "hello" }
hello

在3.0中的ForEach-Object documentation中,他们添加了这个 -

  

由于Windows PowerShell将null视为显式占位符,因此   ForEach-Object cmdlet为$ null生成一个值,就像它一样   管道到它的其他对象。

PS C:\> 1, 2, $null, 4 | ForEach-Object {"Hello"} 
Hello 
Hello
Hello
Hello

$ null的about_automatic_variables文档也针对3.0进行了更新。

Powershell 2.0 $ null文档

$NULL
   Contains a NULL or empty value. You can use this variable to
   represent NULL in commands and scripts instead of using the string
   "NULL". The string can be interpreted as TRUE if it is converted to a
   non-empty string or a non-zero integer.

Powershell 3.0 $ null文档

$NULL
       $null is an automatic variable that contains a NULL or empty value. You
       can use this variable to represent an absent or undefined value in commands
       and scripts.

       Windows PowerShell treats $null as an object with a value, that is, as an
       explicit placeholder, so you can use $null to represent an empty value in a
       series of values.  

       For example, when $null is included in a collection, it is counted as one of
       the objects.

           C:\PS> $a = ".dir", $null, ".pdf"
           C:\PS> $a.count
           3

       If you pipe the $null variable to the ForEach-Object cmdlet, it generates a
       value for $null, just as it does for the other objects.

           PS C:\ps-test> ".dir", "$null, ".pdf" | Foreach {"Hello"}
           Hello
           Hello
           Hello

       As a result, you cannot use $null to mean "no parameter value." A parameter
       value of $null overrides the default parameter value.

       However, because Windows PowerShell treats the $null variable as a placeholder,
       you can use it scripts like the following one, which would not work if $null
       were ignored.

           $calendar = @($null, $null, “Meeting”, $null, $null, “Team Lunch”, $null)
           $days = Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"
           $currentDay = 0

           foreach($day in $calendar)
           {
               if($day –ne $null)
               {
                   "Appointment on $($days[$currentDay]): $day"
               }

               $currentDay++
           } 

           Appointment on Tuesday: Meeting
           Appointment on Friday: Team lunch

注意 - 他们还使foreach关键字的行为与3.0中的ForEach-Object相同(跳过$ null值变量,但将$ null内置转换为可迭代值)但他们没有提到文档中的新行为,就像他们使用ForEach-Obect一样。