因此,您学习使用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
真的是一个因某种原因而被我混淆的数组吗?
答案 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一样。