【问题标题】:searching for multiple strings in multiple files in PowerShell在 PowerShell 中搜索多个文件中的多个字符串
【发布时间】:2021-11-04 09:05:01
【问题描述】:

首先,我有一个可靠的搜索(感谢 Stack Overflow 上的一些帮助),可以检查多个日志文件的一行中不同字符串的出现。

我现在的任务是包含多个搜索,因为有大约 20 个文件和大约十几个搜索条件,我不想访问这些文件超过 200 次。我相信最好的方法是在数组中,但到目前为止我尝试过的所有方法都失败了。

搜索条件由日期、一个固定的字符串 (ERROR) 和一个唯一的 java 类名组成,日期显然每天都在变化。这是我所拥有的:

        $dateStr = Get-Date -Format "yyyy-MM-dd"
        $errword = 'ERROR'
        $word01 = [regex]::Escape('java.util.exception')   
    
        $pattern01 = "${dateStr}.+${errword}.+${word01}"
    
        $count01 = (Get-ChildItem -Filter $logdir -Recurse | Select-String -Pattern $pattern01 -AllMatches |ForEach-Object Matches |Measure-Object).Count
        Add-Content $outfile  "$dateStr,$word01,$count01"

扩展它的简单方法是为我要搜索的每个类设置一个单独的三个命令条目(设置单词,设置模式然后搜索) - 我已经完成并且它有效,但它并不优雅并且然后我们正在处理 >200 个文件来运行搜索。我试图从一个简单的文本文件中读取 java 类,但结果不一,但为了简化对 12 种不同模式的搜索,我唯一能够开始工作的就是它。

【问题讨论】:

  • 您是否尝试过从输入源生成所有组合模式,构建正则表达式 OR,并在您的 S-S 调用中使用它? ///// 同样,S-S-Path 参数将比使用G-C 和流水线阶段更快地读取行。 [咧嘴一笑]
  • Select-String-Pattern 支持字符串数组。试试这个:'One Two Three' |Select-String -Pattern 'One', 'Three',然后这个:'Two Three Four' |Select-String -Pattern 'One', 'Three'(两种搜索模式中的任何一种都匹配两个输入行。)换句话说,你可以这样做:... |Select-String -Pattern $pattern01, $pattern02, $pattern03(这意味着:选择匹配$pattern01的字符串或$pattern02$pattern03

标签: arrays powershell search


【解决方案1】:

iRon 提供了一个重要的指针:Select-String 可以接受要搜索的数组 模式,并报告匹配其中任何一个 的行。

然后,您可以使用 单个 Select-String 调用,结合 Group-Object 调用,允许您将所有匹配的行分组,模式匹配:

# Create the input file with class names to search for.
@'
java.util.exception
java.util.exception2
'@ > classNames.txt

# Construct the array of search patterns,
# and add them to a map (hashtable) that maps each
# pattern to the original class name.
$dateStr = Get-Date -Format 'yyyy-MM-dd'
$patternMap = [ordered] @{}
Get-Content classNames.txt | ForEach-Object {
  $patternMap[('{0}.+{1}.+{2}' -f $dateStr, 'ERROR', [regex]::Escape($_))] = $_
}

# Search across all files, using multiple patterns.
Get-ChildItem -File -Recurse $logdir | Select-String @($patternMap.Keys) |
  # Group matches by the matching pattern.
  Group-Object Pattern |
    # Output the result; send to `Set-Content` as needed.
    ForEach-Object { '{0},{1},{2}' -f $dateStr, $patternMap[$_.Name], $_.Count }

注意:

  • $logDir,顾名思义,假定是指一个目录,在该目录中(递归地)搜索日志文件;将其传递给-Filter 是行不通的,所以我将其删除(然后将$logDir 位置绑定到-Path 参数); -File 将结果限制为文件;如果还存在其他类型的文件,请根据需要添加 -Filter 参数,例如-Filter *.log

  • Select-String-AllMatches 开关通常不需要 - 如果任何模式可以匹配多次每行 并且您想要捕获所有这些匹配项。

  • 使用@(...),散列表键集合周围的array-subexpression operator,即搜索模式,纯粹是出于技术原因需要:它强制集合转换为字符串数组(@ 987654341@),这是-Pattern参数的输入方式。

    • @(...) 的需求令人惊讶,并且可能表明存在错误,从 PowerShell 7.2 开始;见GitHub issue #16061

【讨论】:

    猜你喜欢
    • 2011-04-28
    • 1970-01-01
    • 1970-01-01
    • 2012-05-17
    • 1970-01-01
    • 2011-02-04
    • 2014-10-30
    • 2023-02-21
    相关资源
    最近更新 更多