PowerShell:在日志文件中搜索字符串的一部分



我试图在一系列日志文件中搜索一个模式"Error",然后将结果写入文本文件。

我正在使用命令:

foreach($file in $files){
   $match = get-content $file | Select-String $p | Out-File $matchfile
}

模式$p已从命令行中获取。我在Windows Server 2008 R2上运行该脚本,如果日志文件中的"错误"是一个单词,它会返回结果。我有"错误代码"的实例,我希望脚本能够识别这些实例。

我有我想要的在Windows7上运行的代码。然而,当我在Windows Server 2008 R2上运行该脚本时,没有得到任何结果。两个PowerShell版本都是2.0。

你确定它真的在Windows7上工作吗?按照您的编写方式,foreach循环的每次迭代都会用$files中最后一个文件的结果覆盖匹配文件。您可以在OutFile之后添加-Append开关,但您甚至不需要foreach循环。另外,$match的目的是什么?$match =在我看来是多余的。试试这个:

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

我怀疑你在2K8服务器上没有得到任何结果的原因是$files中的最后一个文件没有匹配$p。在Windows 7计算机上,你会得到结果,因为最后一个文件与$p匹配,但你不会从任何其他文件中得到结果。

I second@Adi,您在每次迭代中都会覆盖文件。您可以通过将Append开关添加到Out-File来解决此问题。这也应该起作用,而且使用起来更简单:

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

我希望$match始终为null。根据帮助,Out File从不发送任何信息。但如果这与你的问题有关,我会感到惊讶。

<小时>

本着"任何帮助都将不胜感激"的精神。。。

我在Win7和WS08R2上都尝试了一个简单的实验,但无法重现您的结果(结果如预期)。我还尝试使用不同的编码创建要搜索的文件:Unicode、UTF8和ASCII。一切都奏效了。我甚至告诉Select String使用错误的编码:

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

它仍然有效。我使用了一个十六进制查看器来验证mytestfile.ascii、mytestfile.unicode和myestfile.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. 

相关内容

  • 没有找到相关文章

最新更新