2

我有以下 Powershell 代码

ls "*.zip" | % {
    $name = $_.name
    if (-not ($name -match '(?<x>\d\d)(?<y>\d{4})\.zip')) { continue }
    $p = $matches["y"] + $matches["x"]
}

该代码在 ISE 中运行良好。但是,如果它在命令行 shell 中运行,则会出现以下错误。

Cannot index into a null array.
At line:3 char:19
+     $p = $matches[ <<<< "y"] + $matches["x"]
    + CategoryInfo           : InvalidOperation: (y:string) [], RuntimeException
    + FullyQualifiedErrorId : NullArray

编辑
我使用if (-not ...) { continue }是因为我不想要太多的大括号缩进。我纠正了这个-not ()问题。(但与错误无关,我测试了名称始终为xxx999999.zip格式的文件)

4

3 回答 3

3

首先一个 ')' 之后丢失.zip'(可能是错字)

其次,只需尝试在您的比赛周围添加 ()

ls "*.zip" | % { 
    $name = $_.name 
    if (-not ($name -match '(?<x>\d\d)(?<y>\d{4})\.zip$')) { continue } 
    $p = $matches["y"] + $matches["x"] 
} 

第三continue避免处理管道的末端,你可以试试

ls "*.zip" | % { 
    $name = $_.name;
    Write-Host $name;
    if ($name -match '(?<x>\d\d)(?<y>\d{4})\.zip$'){
    $p = $matches["y"] + $matches["x"] 
    }
} 

它也在 Powershell 命令行中工作

ls "*.zip" | % {$name = $_.name; if ($name -match '(?<x>\d\d)(?<y>\d{4})\.zip$') { $p = $matches["y"] + $matches["x"]}}
于 2012-08-03T03:46:52.083 回答
2

您的问题是ifand 运算符优先级:

-not $name -match '...'

被解析为

(-not $name) -match '...'

因此你有

'False' -match '...'

不匹配,因此$Matches为空。在 ISE 中,您可能仍然有$Matches一个早期测试的旧物。

作为一个简单的解决方案,只需使用-notmatch

$name -notmatch '...'

这符合您的期望。或者在操作周围添加括号-match,但否定运算符更容易恕我直言。

编辑: JPBlanc 在他对您的回答的评论中实际上是正确的,这里更根本的问题是您的问题continue,因为它在第一次应用时立即结束了管道。所以你实际上需要使用以下方式:

if ($name -match '...') {
  ...
}

但是,当然,您-not从上面的问题仍然是一个,尽管解决它对您没有多大帮助。

于 2012-08-03T05:40:02.813 回答
-3

这听起来像是一个范围问题。在 ISE 中,$matchesif. 但是,在命令行 shell 中,它仅在if.

Powershell 确实需要有严格的语言定义。


但是,如果所有状态都写在一行中,情况就不同了。

ls | %{ $name = $_.name; if (-not ($name -match '(?<d>dip)')) { continue; };  $p = $matches["d"]; "$name : $p"  }

有时 Powershell 只是不可预测的。

于 2012-08-03T04:54:28.307 回答