2012-08-03 23 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

相關問題