2013-06-21 98 views
2

我試圖在一系列日誌文件中搜索模式「錯誤」,然後將結果寫入文本文件。PowerShell:在日誌文件中搜索字符串的一部分

我使用命令:

foreach($file in $files){ 

    $match = get-content $file | Select-String $p | Out-File $matchfile 
} 

模式$ P已經在命令行欺騙。 我在Windows Server 2008 R2上運行腳本,如果「錯誤」是日誌文件中的單個單詞,則它會返回結果。我有我想讓腳本識別的「ErrorCode」實例。

我有代碼在Windows 7上工作,因爲我想。我在Windows Server 2008 R2上運行腳本時沒有得到任何結果。兩個PowerShell版本都是2.0。

+0

模式錯誤應該匹配錯誤和ErrorCode。究竟是什麼使用的模式? – zdan

回答

2

您確定它實際上在Windows 7上工作嗎?他們用這種方式編寫它,foreach循環的每次迭代用$ files中最後一個文件的結果覆蓋匹配文件。您可以在Out-File之後添加-Append開關,但您甚至不需要foreach循環。另外,$匹配的目的是什麼? $match =對我來說看起來是多餘的。試試這個:

Get-Content $files | Select-String $p | Out-File $matchfile 

我懷疑你沒有得到2K8服務器上的任何結果的原因是,在$文件中的最後一個文件有沒有爲$ P匹配。在Windows 7機器上,您獲得的結果是因爲最後一個文件與$ p匹配,但是您沒有從任何其他文件獲取結果。

+0

我認爲它在Windows 7上工作的原因是因爲最後一個日誌文件包含該模式。很明顯,這是不對的,而且我有點慢,而你恰恰是這個問題!非常感謝你! :) – user2509413

0

我第二@Adi,你在每次迭代覆蓋文件。您可以通過將追加開關添加到Out-File來解決此問題。這應該也工作,更簡單的使用:

$files | Select-String $p | Out-File $matchfiles 
0

我希望$匹配將始終爲空。根據幫助,Out-File從不向管道發送任何東西。但如果這與您的問題有關,我會感到驚訝。


本着「任何幫助將不勝感激」 ......

我試過兩個Win7和WS08R2一個簡單的實驗,不能瑞普你的結果(它的工作如預期)。我也嘗試使用不同的編碼創建正在搜索的文件:Unicode,UTF8和ASCII。一切正常。我甚至告訴Select-String使用錯誤的編碼:

get-content mytestfile.ascii | select-string error -Encoding Unicode 

它仍然有效。我使用了十六進制查看器來驗證mytestfile.ascii,mytestfile.unicode和mytestfile.utf8實際上是以不同的方式編碼的。我也嘗試了不同的行結尾(Linux風格與Windows風格)並且工作。

我的猜測是,你有一些獨特的文件,系統等,將不得不通過一些探測發現。考慮到這一點......


我建議你看看裏面你的日誌文件與一個十六進制查看器(兩個系統嘗試),看看什麼是你的Win7系統,你的WS08R2系統之間的不同之一。在UTF8文件的開始部分,您將看到EF BB BF,然後每個字符的日誌會顯示一個字節。在Unicode文件的開始處,您將看到FF FE,然後每個字符顯示兩個字節。 (如果文本是英文,則其他字符將爲0)。對於ASCII文件,在開始時沒有特別的值,每個字母有一個字節。 Linux行結尾是單個0A(換行符),Windows行結束符是0D 0A(回車符,換行符)。除了上面提到的開頭的特殊字符,以及行結尾,您將要查找的文本與在記事本中查看文本完全相同。 (順便說一下,如果行結尾是Windows風格,在記事本中查看它只會看起來「正確」)。如果你看到任何額外的字符,那麼這可能是問題的根源

如果這沒有顯示任何意外,那麼我建議從Powershell命令行進行一系列實驗。以下程序列出了很多步驟,但它試圖涵蓋許多意外情況。你不會執行每一步。 (但是,在開始時進行一些修改 - 爲了說明您用於測試的日誌文件中出現「錯誤」的位置 - 您可以複製並粘貼整個腳本,然後一次解釋整組結果)

# 0. Get some text to experiment with 
# If "error" appears on line 200 and line 493 (where first line in file is Line 1), then: 
$testTxt= cat mylogfile | select-object -skip 195 -first 300 
# or better still: 
$testTxt= cat mylogfile | select-object -skip 195 -first 10 
$testTxt2= cat mylogfile | select-object -skip 488 -first 10 
$testTxt += $testTxt 

# 1. Figure out where in testTxt "error" appears 
$testTxt[3..5] # if my math is right "error" will appear as middle line 

# 2. If #1 doesn't work on both systems, then on failing system(s): 
$testTxt[4] | select-string error 

# 2.5 If #2 fails then you need to look at every character 
# of $testTxt 
[char[]]$testTxt 
# or even look at every byte value in hex: 
[byte[]][char[]]$textTxt | % { $_.tostring("X")} 

# 3. If #2 worked, then: 
$testTxt | select-string error 

# 4. If #3 failed, then: 
$testTxt[3..5] | select-string error 

# 5. If #4 failed, then: 
$testTxt[3..4] | select-string error 
$testTxt[4..5] | select-string error 

# 6. If either of #5 failed, then carefully examine those lines of text: 
"line 3" 
[char[]]$testTxt[3] 
"line 4" 
[char[]]$testTxt[4] 
"line 5" 
[char[]]$testTxt[5] 

# 7. If #3 worked then: 
$testTxt2 = cat myLogFile 
$testTxt2 | select-string error 

# 8. If #7 worked, then you have a solution 
# Replace: 
get-content $file | Select-String $p | Out-File $matchfile 
# With (on Powershell v3 this may perform worse than the above, assuming above worked) 
$logText = get-content $file 
$logText | Select-String $p | Out-File $matchfile 

# 9. If #8 failed, then the situation is somewhat awkward. 
# On one hand you have twenty lines working, but on the other the file as a whole 
# doesn't work. You could go back to step #0 and start with a larger amount of text, 
# say 40 lines, and see if it works. If it does you could try 80, 160, etc. until it 
# fails. But this case seems pretty unlikely. 

# 10. In general when a step fails you want to try something "smaller". And when steps 
#  succeed you want to try something "bigger", where "bigger" means more like the 
#  solution you want.