PowerShell 下的 grep —— Select-String 详解及二者对比

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/sinat_41104353/article/details/83046182

使用 help Select-String -ShowWindow 命令我们可以很容易的得到一份中文的帮助文档,其中有这样两段话:

  1. Select-String cmdlet 在输入字符串和文件中搜索文本和文本模式。你可以像使用 UNIX 中的 Grep 和 Windows 中的 Findstr 一样来使用它。可以键入“Select-String”或其别名“sls”。
  2. Select-String 类似于 UNIX 中的 Grep 命令和 Windows 中的 FindStr 命令。


熟悉 Linux/Unix 的朋友们都知道,grep 命令有这样如下常见的参数:
在这里插入图片描述
本文将使用 Select-String 来对这些功能进行一一实现。

由于 grep -n 是列出每一个符合条件的行号,而 PowerShell 默认就会输出行数,这里不再提此。

递归搜索

对比 grep -r
使用 Get-ChildItem -Path 文件路径 -Recurse | select-string -pattern "模式"
例子:我在 E:\2笔记&&资料\test 有一个文件 FactoryPattern.txt 和若干目录:
在这里插入图片描述
用上述命令结果如下(因为我已经 cd 到此目录下了,故没指定 -Path)
在这里插入图片描述
输出有点乱,看不出文件层次,不知道有没有更美观的方法, 希望有人能够给出建议。下图是 grep 的,也有点乱:
在这里插入图片描述

https://antjanus.com/blog/web-development-tutorials/how-to-grep-in-powershell/ 找到了美观输出的方法。显示的有点不对…

PS E:\2笔记&&资料\test> Get-ChildItem -Recurse | Select-String -Pattern "干" | Select Filename, LineNumber, Line, Path | Format-Table

在这里插入图片描述

区分大小写

对比 grep -i
使用开关参数(SwitchParameter) -CaseSensitive
默认情况下,匹配项不区分大小写。

只打印出匹配行的数量

对比 grep -c

PS C:\>$f = select-string -path audit.log -pattern "logon failed"
PS C:\>$f.count

第二个命令使用对象数组的 Count 属性来显示找到的匹配项数
比如说,有4行有 logon failed 这个 pattern,输出就是 4。

捕获具有匹配项的行前后的指定行数

对比 grep -C N
-Context <Int32[]>

PS C:\>$f = select-string -path audit.log -pattern "logon failed" -context 2, 3

此命令将在 Audit.Log 文件中搜索短语“logon failed”。它使用 Context 参数来捕获匹配项的前 2 行和后 3 行。

搜索多个匹配项(贪婪模式)

使用开关参数 -AllMatches
在每个文本行中搜索多个匹配项。在没有此参数的情况下,Select-String 只会查找每个文本行中的第一个匹配项。
这个参数帮助文档是这样写的,但是其作用我也不太知道,因为 Select-String 默认好像也可以以搜全。

匹配多个模式

对比 grep -e 表达式
来自 https://cloud.tencent.com/developer/ask/41837

例如搜索C:\Logs that contain the words "VendorEnquiry"和“Failed”的所有文件

方法一

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',...

方法三

如果要按任意顺序匹配这两个单词,使用:

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

反转

对比 grep -v
使用开关参数 -NotMatch
查找与指定的模式不匹配的文本。

不要求输出

对比 grep -q
使用开关参数 -Quiet
返回布尔值(true 或 false),而不是 MatchInfo 对象。如果找到该模式,则该值为“true”;否则为“false”。

从文件读取匹配模式 pattern

对比 grep -fgrep --file=filename 。其中 filename 指的是一个含有多行文本的文件名,而每行文本是一个匹配模式。

Get-Content .\doc.txt | Select-String -Pattern (Get-Content .\regex.txt)

其中 .\regex.txt 是那个每行都是一个匹配模式的文件,而 .\doc.txt 则是我们要搜索的文件。
参考 https://stackoverflow.com/questions/15199321/powershell-equivalent-to-grep-f


至于 grep-w word-l-h 没见过实际例子,这里不提。


突然发现 PowerShell 下使用 grep 可以搜中文,而 cmd 下面的搜不了…
在这里插入图片描述
在这里插入图片描述
这就是说使用 PowerShell 既可以使用 Linux/Unix 命令带来的便捷还可以使用 PowerShell 提供的命令,就好像手上有了两把武器。

当然此文侧重在简单对比,Select-String 和 grep 的其他高级用法这里并没有涉及。

猜你喜欢

转载自blog.csdn.net/sinat_41104353/article/details/83046182