Powershell陷阱
Powershell陷阱
你遇到了哪些PowerShell的陷阱呢? 🙂
我的例子如下:
# ----------------------------------- function foo() { @("text") } # 预期是1,实际上是4。 (foo).length # ----------------------------------- if(@($null, $null)) { Write-Host "预期能运行到这里,实际上也可以运行到这里。" } if(@($null)) { Write-Host "预期能运行到这里,但是永远不会。" } # ----------------------------------- function foo($a) { # 我以为这样是对的。 #if($a -eq $null) #{ # throw "你不能将$null作为参数传递。" #} # 实际上应该是这样的: if($null -eq $a) { throw "你不能将$null作为参数传递。" } } foo @($null, $null) # ----------------------------------- # 有try/catch,但是没有报告调用栈。 function foo() { bar } function bar() { throw "测试" } # 预期结果: # 在bar()行:XX # 在foo()行:XX # # 实际结果类似于: # 在bar()行:XX foo
希望知道你们遇到的陷阱,以便避免它们的影响 🙂
在使用PowerShell时,有一个常见的错误是不正确处理表达式,默认情况下会将其写入到管道中。当你没有意识到某个函数返回一个值时,这会非常令人烦恼。
例如,考虑以下函数示例:
function example() { param ( $p1 ) if ( $p1 ) { 42 } "done" }
在上面的示例中,我们定义了一个名为example的函数,它接受一个参数$p1。如果$p1为真,函数会返回值42,否则返回字符串"done"。
现在,假设我们调用这个函数并传入一个为真的参数:
PS> example $true
结果会是:
42 "done"
这是因为我们没有正确处理函数返回的值。实际上,当我们调用函数时,函数的返回值会被写入到默认的输出管道中。在这种情况下,返回值42被输出了出来,然后才是字符串"done"。
要解决这个问题,我们需要显式地处理函数的返回值。我们可以使用变量来存储返回值,或者使用管道操作符将其发送到其他命令中。
以下是解决这个问题的两种方法:
1. 使用变量存储返回值:
$value = example $true
现在,返回值42会被存储在变量$value中,而不会被写入到默认的输出管道中。
2. 使用管道操作符将返回值发送到其他命令中:
example $true | Out-Null
在这个例子中,我们使用了Out-Null命令将返回值42丢弃,而不会将其写入到默认的输出管道中。
通过正确处理函数的返回值,我们可以避免这个PowerShell陷阱,并确保程序的行为符合预期。
Powershell陷阱:无法在空值表达式上调用方法的问题
在上述代码中,当Get-ChildItem命令没有返回任何结果时,$files被赋值为$null。然后,foreach语句将会对一个标量值进行循环,即使这个标量值是$null。在循环中,当尝试调用$file.Fullname.substring(2)时,会出现错误提示"无法在空值表达式上调用方法"。
为了解决这个问题,可以将Get-ChildItem命令的结果放入@()中,即@(Get-ChildItem . -inc *.extdoesntexist)。这样,无论命令返回0个、1个还是多个结果,都将得到一个数组。需要注意的是,如果命令返回的本身已经是数组,使用@(命令)将不会产生额外的数组包装。
值得一提的是,从PowerShell V3开始,foreach不再仅对$null进行迭代。也就是说,对于foreach( $d in $null ) { "This never displays!" }
,将会按照字面意思执行,不会进入循环。然而,强制将结果转换为数组的做法仍然非常常见,并且是一个良好的编程习惯。
Powershell pitfalls(Powershell陷阱)的问题是出现在使用函数参数时的语法错误。问题的原因是在调用函数时,参数使用了括号,导致将参数视为数组而不是多个单独的参数。解决方法是在调用函数时去除括号,直接使用空格分隔多个参数。
在Powershell中,函数的参数可以使用括号将多个参数括起来,以便传递给函数。然而,在上述示例中,函数foo被调用时使用了括号,导致将参数1和参数2视为一个数组,而不是两个单独的参数。因此,当函数试图使用第二个参数时,会抛出错误。
为了解决这个问题,我们需要将函数调用的括号去除,直接使用空格分隔多个参数。这样,函数foo将会正确接收两个单独的参数。
这个问题让人想起了VB和VBScript处理参数括号的方式。在VB和VBScript中,使用括号调用函数和不使用括号调用函数是不同的,使用括号调用函数会忽略返回值并强制使用括号,而不使用括号调用函数则不能使用括号。
总结起来,当在Powershell中调用函数时,需要注意不要使用括号将多个参数括起来,而是使用空格分隔多个参数。这样可以避免出现类似的语法错误。