2012-08-03 72 views
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格局中的文件)

回答

-3

工作这听起来像一个范围问题。在ISE中,$matchesif之后的代码可见。但是,在命令行shell中,它只在if的脚本块中可见。

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


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

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

有时Powershell只是不可预测的。

+2

PowerShell *具有*语言规范。在ISE和命令行中,语言的运行方式相同(实际上,主机cmdlet的行为不同)。毕竟这是整个问题。 – Joey 2012-08-03 05:37:39

+2

请注意,您的代码省略了他们犯的实际错误。这是它工作的原因。我会说程序员在这里是不可预知的,而不是语言。 – Joey 2012-08-03 05:40:53

+2

此外,在第一次找到不匹配的文件时继续中止管道。 – JPBlanc 2012-08-03 06:03:56

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"]}} 
+0

是的,缺少'''是一个错字。 – ca9163d9 2012-08-03 04:54:58

+1

只是一个方面的评论,这应该没有什么效果:。正则表达式中的.zip并不真正匹配.zip - >它匹配 zip。你可能通过使用basename属性和'$'anchor来摆脱它,以确保这个数字部分在最后。目前它也会匹配1234567zipFooBar.zip – BartekB 2012-08-03 08:44:36

+0

你是对的,我想念这个旧评论。 – JPBlanc 2014-06-06 05:21:19

2

你的问题是if和运算符优先级:

-not $name -match '...' 

被解析为

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

因此你必须

'False' -match '...' 

不匹配,从而$Matches是空的。在ISE中,你可能还有一个老的$Matches在早期的测试中。

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

$name -notmatch '...' 

你所期望它做。或者在-match操作周围添加括号,但否定运算符更容易。

编辑: JPBlanc在他对你的解答评论确实是正确的,更根本的问题这里是你的continue不能工作,因为它立即结束管道上适用第一次。所以,你实际上需要使用方式如下:

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

但当然的问题,您-not从上面仍然之一,虽然解决它并不能帮助你多少。

+0

+1更好的解释,但相同的结论。 – JPBlanc 2012-08-03 05:57:18

+0

JPBlanc,其实你是对的,'继续'是问题所在。所以这个答案是错误的。 – Joey 2012-08-03 07:22:59

相关问题