2

一連のログファイルでパターン「エラー」を検索し、結果をテキストファイルに書き込もうとしています。

私はコマンドを使用しています:

foreach($file in $files){

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

パターン $p はコマンドラインから取り込まれました。Windows Server 2008 R2 でスクリプトを実行していますが、ログ ファイル内の「エラー」が 1 つの単語である場合に結果が返されます。スクリプトで識別したい「ErrorCode」のインスタンスがあります。

私が望むように、コードは Windows 7 で動作しています。ただし、Windows Server 2008 R2 でスクリプトを実行しても結果が得られません。どちらの PowerShell バージョンも 2.0 です。

4

3 に答える 3

0

@Adi の 2 番目に、各反復でファイルを上書きしています。Append スイッチを に追加することで、これを解決できますOut-File。これも機能するはずで、使いやすいです。

$files | Select-String $p | Out-File $matchfiles
于 2013-06-21T17:28:16.233 に答える
0

$match は常に null になると思います。ヘルプによると、Out-File はパイプラインに何も送信しません。しかし、それがあなたの問題に関連しているとしたら、私は驚くでしょう.


「どんな助けでも大歓迎です」の精神で...

Win7 と WS08R2 の両方で簡単な実験を試みましたが、結果を再現できませんでした (期待どおりに動作しました)。また、Unicode、UTF8、および ASCII というさまざまなエンコーディングで検索対象のファイルを作成してみました。すべてが機能しました。Select-String に間違ったエンコーディングを使用するように指示しました。

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

それでも機能しました。16 進ビューアーを使用して、mytestfile.ascii、mytestfile.unicode、および mytestfile.utf8 が実際にはすべて異なる方法でエンコードされていることを確認しました。また、さまざまな行末 (Linux スタイルと Windows スタイル) を試してみましたが、うまくいきました。

私の推測では、ファイルやシステムなどに独自の何かがあり、それを調査して発見する必要があると思います。それを念頭に置いて...


Win7 システムと WS08R2 システムの間で何かが異なるかどうかを確認するために、16 進ビューアー (両方のシステムから試してください) を使用してログファイルの 1 つを調べることをお勧めします。UTF8 ファイルの先頭に EF BB BF が表示され、次にログの各文字に 1 バイトが表示されます。Unicode ファイルの先頭に FF FE が表示され、次にすべての文字に 2 バイトが表示されます。(テキストが英語の場合、1 文字おきに 0 になります)。また、ASCII ファイルの場合、先頭に特別な値はなく、1 文字あたり 1 バイトです。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. 
于 2013-06-21T17:51:09.783 に答える