【问题标题】:PowerShell: Searching for a part of a string in a logfilePowerShell:在日志文件中搜索字符串的一部分
【发布时间】:2013-06-21 14:57:16
【问题描述】:

我正在尝试在一系列日志文件中搜索模式“错误”,然后将结果写入文本文件。

我正在使用命令:

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。

【问题讨论】:

  • 模式 "Error" 应该匹配 Error 和 ErrorCode。究竟使用的是什么模式?

标签: powershell select-string


【解决方案1】:

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

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

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

【讨论】:

  • 我认为它在 Windows 7 上运行的原因是因为最后一个日志文件包含该模式。显然这是不对的,而且我有点慢,而你完全正确,这就是问题所在!非常感谢你! :)
【解决方案2】:

我第二个@Adi,您在每次迭代中都覆盖了文件。您可以通过将 Append 开关添加到 Out-File 来解决此问题。这也应该有效并且使用起来更简单:

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

【讨论】:

    【解决方案3】:

    我希望 $match 将始终为空。根据帮助,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. 
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-04-10
      • 1970-01-01
      • 2016-01-19
      • 2013-02-11
      • 1970-01-01
      • 2011-11-19
      • 2011-08-10
      • 2017-09-10
      相关资源
      最近更新 更多