2012-10-10 20 views
0

這是在powershell -noprofile中的Windows XP SP3上的Powershell v2中運行的。當從腳本運行但在控制檯中成功時,PowerShell切換正則表達式會失敗

如果我將它複製並粘貼到控制檯中,下面的Powershell腳本可行,但如果將它作爲腳本運行,則不起作用。任何人都可以看到什麼可能造成的?

該腳本如下(有些名稱已被更改,以保護無辜)。

#Known Error values to count instances of 
$KnownErrorText = @" 
Invalid Descriptor Index 
Syntax error or access violation 
An error occurred while attemping to update a record 
Message from LDAP server: Invalid credentials 
Error sending data over TCP connection 
"@ 

#Fix the variable so it's an array 
$KnownErrorText = $knownErrorText.split("`n") 

#output variables 
$KnownErrors = @{} 
$UnknownErrors = @() 

#Generate the hash to contain counts of the the known errors 
foreach ($line in $knownErrorText) {$KnownErrors.Add($line,0)} 

#Get error lines from the log 
$scerrors = Select-String -Path "\\myserver01\d$\logs\application.log" -Pattern "Error" 

"$($scerrors.count) errors to process" 
$ProcessedErrors = 1 

#Look at each error. Pass the error through a switch to identify whether it's 
#a known error or not. If it's Known, increment the appropriate count in the hash 
#if it's not known, add it to the unknown errors output variable 
foreach ($e in $scerrors) { 
    "$($ProcessedErrors)`tProcessing`t$($e.line)" 
    $addToUnknown = $true 
    "e.line type:`t$($e.line.gettype().name)`tLength$($e.line.length)" 
    switch -regex ($knownErrorText) { 
      #Look in the text of the current error for the any of the errors in 
      #the KnownErrorText array 
      #THIS IS THE PART THAT DOESN'T WORK WHEN RUNNING IN A SCRIPT 
    {"$($e.line)" -match "^.*$($_).*`$"} { 
     Write-host "Matched $($_)" -ForegroundColor Green -BackgroundColor Black 
     $KnownErrors.Set_Item($_,([int]$KnownErrors.Get_Item($_))+1) 
     $addToUnknown = $false 
        #We found our match so stop 
        #processing the KnownErrorText array through the switch 
     break 
    } 
    default { 
     Write-host "UnMatched`t$($_)" -ForegroundColor Red -BackgroundColor Black 
    } 
} 

    #If we got through all the KnownErrorText values without finding a match, 
    #add the error to the UnknownErrors array to be displayed 
if ($addToUnknown) {$UnknownErrors += $e} 

$ProcessedErrors++ 
if ($ProcessedErrors -ge 5) {break} 
} 

#Console reporting 
"Known Errors:" 
$KnownErrors.GetEnumerator() | Sort-Object Value -Descending 
"" 
"$($UnknownErrors.count) Unknown Errors:" 
$UnknownErrors | Foreach {$_.line} 

當我運行這是一個腳本(例如,如果保存到C:\ TEMP \ ErrorReporting.ps1,並呼籲與 & c:\Temp\ErrorReporting.ps1

匹配部分失敗:

{"$($e.line)" -match "^.*$($_).* $「} `

回答

1

問題是由於字符串拆分操作在腳本和控制檯中的工作方式不同。粘貼到控制檯可能會產生保存的腳本文件包含的不同行尾(\r\n vs \n)。所以這將有助於明確指定$knownErrorText數組,而不是分割字符串來產生它。

$knownErrorText = 'Invalid Descriptor Index', 
        'Syntax error or access violation', 
        ... 

旁白:

您沒有使用switch -Regex如預期。標準的用法是不要有一個scriptblock,它可以比較定義案例,而只是提供一個輸入匹配的regex字符串。對於如果你正在做scriptblocks定義的情況下內部檢查例如

$myStr = 'abc123' 
switch -regex ($myStr) 
{ 
    'abc\d\d\d' { 'abc with 3 numbers'; break } 
    'xyz\d\d\d' { 'xyz with 3 numbers'; break } 
} 

,你其實並不需要-regex標誌都沒有。

您的目標似乎是檢查$e.Line是否包含任何已知的錯誤消息。如果是這樣,那麼開關可能不是最好的工具,反正。你可以做到這一點非常簡單,如下所示:

foreach ($e in $scerrors) 
{ 
    if($knownErrors |?{$e.Line -match $_}) 
    { 
     "$($e.Line) matches a known error" 
    } 
    else 
    { 
     "$($e.Line) does not match a known error" 
    } 
} 
+0

這種結構與開關結構有同樣的結果。如果粘貼到控制檯窗口中,它可以正常工作,但在作爲腳本運行時無法評估匹配。 –

+0

也許這是錯誤的字符串拆分 - 粘貼到控制檯可能會導致不同的行結束比您的腳本文件中的結尾。你爲什麼要做一個'Split'而不是僅僅把'$ knownErrorText'定義爲一個數組呢? '$ knownErrorText ='error1','error2','error3'' – latkin

+0

如果測試條件不是字符串(在這種情況下是表達式),那麼-regex開關將被忽略。 – zdan

相關問題