如何使用PowerShell的select-string命令在文件中查找多个模式?

40
我想在一个目录中搜索多个字符串的文件,然而使用"select-string -pattern"无法实现。请问有谁可以告诉我如何做到这一点?
示例:搜索所有包含单词“VendorEnquiry”和“Failed”的C:\Logs目录中的文件,并且日志时间为上午11:30。文件的结构可能不同(例如,不同的标记名称等)。
... <methodException>VendorEnquiry</methodException> ...
... <logTime>13/10/2010T11:30:04 am</logTime> ...
... <status>Failed</status> ...

... <serviceMethodException>VendorEnquiry</serviceMethodException> ...
... <logTime>13/10/2010</logTime> ...
... <serviceStatus>Failed</serviceStatus> ...

谢谢。

3个回答

43

如果您想匹配这两个单词,无论顺序如何,请使用:

gci C:\Logs| select-string -pattern '(VendorEnquiry.*Failed)|(Failed.*VendorEnquiry)'
如果在该行中Failed总是出现在VendorEnquiry之后,只需使用:

如果在该行中 Failed 总是出现在 VendorEnquiry 之后,只需使用:

gci C:\Logs| select-string -pattern '(VendorEnquiry.*Failed)'

33

为了在每个文件中搜索多个匹配项,我们可以按顺序调用几个Select-String命令:

Get-ChildItem C:\Logs |
  where { $_ | Select-String -Pattern 'VendorEnquiry' } |
  where { $_ | Select-String -Pattern 'Failed' } |
  ...

每一步,不包含当前模式的文件将被过滤掉,确保最终文件列表包含所有搜索项。

我们可以通过一个筛选器来简化这个过程,而不是手动编写每个Select-String调用来匹配多个模式:

filter MultiSelect-String( [string[]]$Patterns ) {
  # Check the current item against all patterns.
  foreach( $Pattern in $Patterns ) {
    # If one of the patterns does not match, skip the item.
    $matched = @($_ | Select-String -Pattern $Pattern)
    if( -not $matched ) {
      return
    }
  }

  # If all patterns matched, pass the item through.
  $_
}

Get-ChildItem C:\Logs | MultiSelect-String 'VendorEnquiry','Failed',...
现在,要满足示例中“大约上午11:30的日志时间”这部分需要找到与每个故障条目对应的日志时间。如何做这取决于文件的实际结构,但测试“about”的方法相对简单:
function AboutTime( [DateTime]$time, [DateTime]$target, [TimeSpan]$epsilon ) {
  $time -le ($target + $epsilon) -and $time -ge ($target - $epsilon)
}

PS> $epsilon = [TimeSpan]::FromMinutes(5)
PS> $target = [DateTime]'11:30am'
PS> AboutTime '11:00am' $target $epsilon
False
PS> AboutTime '11:28am' $target $epsilon
True
PS> AboutTime '11:35am' $target $epsilon
True

27

您可以在数组中指定多个模式。

select-string VendorEnquiry,Failed C:\Logs

这也适用于-notmatch:

select-string -notmatch VendorEnquiry,Failed C:\Logs

2
同意。这对我来说完美地解决了问题,比其他答案简单得多。 - Dave Montgomery
1
是的,我的回答有些被删除或被一些人标记为负面,但也有些人会给我点赞。 - js2010
我原本想说其他海报也包含了更具体地针对原问题的内容...但其实并没有。他们在解释命令的使用方面做得很好,但这有什么用呢?原问题很模糊,所以答案可以是任何东西。我想说,就问题而言,这个答案和其他任何答案一样好。 - David T. Macknet
这将列出具有元素之间OR关系的文件。也就是说,如果一个文件只有“VendorEnquiry”,它将被列出。如何查找既必须具有“VendorEnquiry”又必须具有“Failed”的文件?换句话说,模式数组的元素之间存在AND关系。 - qqqqq
1
@qqqqq 我想你可以用 get-content file | select-string pattern1 | select-string pattern2 这个命令,也可以使用 get-content -raw 一次性获取所有字符串。 - js2010

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接