【问题标题】:How to grep, excluding some patterns?如何grep,排除一些模式?
【发布时间】:2013-08-30 09:27:39
【问题描述】:

我想在文件中找到出现某种模式但不存在某种其他模式的行。例如,我需要找到包括loom 在内的所有文件/行,但gloom 除外。所以,我可以通过命令找到loom:

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

现在,我想搜索 loom,不包括 gloom。但是,以下两个命令都失败了:

grep -v 'gloom' -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
grep -n 'loom' -v 'gloom' ~/projects/**/trunk/src/**/*.@(h|cpp)

我应该怎么做才能实现我的目标?

编辑 1: 我的意思是 loom 和 gloom 是字符序列(不一定是单词)。所以,例如,我在命令输出中需要bloomberg,不需要ungloomy。

编辑 2: 有我的期望示例。 以下两行都在命令输出中:

我通过香的面纱面对隐约可见的图标。

Arty 在忧郁的日子里慢慢消散。

以下两行均不在命令输出中:

这是 gloomyin' 太可怕了 - 伟大的 muckle doolders o' cloods。

在高pyntit大厅的西南环

【问题讨论】:

  • 您是否正在寻找符合您的标准的文件?
  • 我正在寻找符合我标准的行的文件。我想查看所有集合文件名 + 匹配行数 + 匹配行本身的列表。
  • 如果该行是there is a loom in the gloom - 你想打印那行吗?只是想了解您是否只是在寻找 loom 出现的行而不是作为 gloom 的一部分,或者您是否真的想排除包含 gloom 的行,即使 loom 出现在它自己的其他地方。发布一些示例输入和预期输出会有所帮助。
  • 所以你的问题真的是How do I find lines containing the string "loom" where "loom" is not preceded by the letter "g"?如果您发布了一些示例输入和所需的输出,那将有很大帮助。该问题的答案包含在下面的答案中。
  • @EdMorton - 是的,你是对的 - 我需要所有行,其中出现 loom 之前没有 g。 (对不起。我昨天开始评论,但没有完成。不小心发送了这条评论。)

标签: bash grep


【解决方案1】:

链接 grep 怎么样?

grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

【讨论】:

  • 及时。完美运行。 -v 是排除的选项。谢谢
  • 来自问题:所以,例如,我需要在命令输出中使用bloomberg 而不需要ungloomy。 如果单行包含'...并且布隆伯格对前景不甚乐观……',您会删除该行但它是需要的(因为如果包含bloomberg)。
【解决方案2】:
grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'

【讨论】:

  • 来自问题:所以,例如,我需要在命令输出中使用bloomberg 而不需要ungloomy。 如果单行包含'...并且布隆伯格对前景不乐观......',你会删除那条线但它是想要的(因为如果包含bloomberg)。
  • @JonathanLeffler "我需要找到所有的文件/行,包括 loom,除了那些带有阴影的文件/行。"
【解决方案3】:

您可以使用支持negative lookbehind的grep -P(perl 正则表达式):

grep -P '(?<!g)loom\b' ~/projects/**/trunk/src/**/*.@(h|cpp)

我为单词边界添加了\b。

【讨论】:

  • 您不需要向后看,\([^g]\|^\) 有效。这并不排除带有loom 和gloom 的行。
  • @Kevin: OP 想用 loom 查找行但not gloom。
  • 没错。如果一条线两者都有,他不想要它,但无论如何这都会匹配它。
  • @Kevin:这不会匹配 gloom 但会匹配 loom(正如 OP 想要的那样)。
  • 来自问题:所以,例如,我在命令输出中需要bloomberg 而不需要ungloomy。 因此,单词边界会适得其反.
【解决方案4】:

另一个没有链接的解决方案grep:

egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)

在括号之间,您在出现loom 之前排除字符g,除非loom 是该行的第一个字符。

【讨论】:

    【解决方案5】:

    /*你可能看起来像这样?

    grep -vn "gloom" `grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)`
    

    BACKQUOTES 用作命令的括号,因此在这种情况下启用-l, BACKQUOTES 中的代码将返回文件名,然后使用 -vn 执行您想要的操作:拥有文件名、行号以及实际行。

    更新或使用 xargs

    grep -l "loom" ~/projects/**/trunk/src/**/*.@(h|cpp) | xargs grep -vn "gloom"
    

    希望有帮助。*/

    请忽略我上面写的,这是垃圾。

    grep -n "loom" `grep -l "loom" tt4.txt` | grep -v "gloom"
    
                   #this part gets the filenames with "loom"
    #this part gets the lines with "loom"
                                              #this part gets the linenumber,
                                              #filename and actual line
    

    【讨论】:

      【解决方案6】:

      用awk就行了,比grep简单多了,让你清楚地表达复合条件。

      如果您想跳过同时包含loom 和gloom 的行:

      awk '/loom/ && !/gloom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
      

      或者如果你想打印它们:

      awk '/(^|[^g])loom/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
      

      如果实际情况是您只想要 loom 本身作为一个单词出现的行:

      awk '/\<loom\>/{ print FILENAME, FNR, $0 }' ~/projects/**/trunk/src/**/*.@(h|cpp)
      

      【讨论】:

      • 想一想如何编写一个 grep 命令来获取包含 abc 和 def 和 ghi 的行,这些行以任意顺序排列。现在将其与awk '/abc/ &amp;&amp; /def/ &amp;&amp; /ghi/' 进行比较。现在想想在这个页面上的答案中是如何写出相当于awk '/loom/ &amp;&amp; !/gloom/' 的grep 的。
      • 我对 awk 不是很熟悉,显然有关于这个命令的书籍。现在我对 grep 很好,也许有一天我会和你说同样的话。 :)
      • awk 是用于处理文本文件的标准 UNX 工具(即在所有 UNIX 安装上都可用)。这就是它被发明的目的,而且它非常擅长。如果您使用 UNIX 并解析文本文件,请从 Arnold Robins 的《Effective Awk Programming, Third Edition》一书中学习 awk。有一个小的范式转变需要克服与 awks condition { action } 语法相关的问题,但对于任何具有任何 C 或其他基于 Algol 语言经验的人来说,这都是轻而易举的事。
      • 奖励:输出类似于grep -Hn --color:awk '/loom/ &amp;&amp; !/gloom/ { gsub(/loom/, color("1;31") "&amp;" color(0)); print color(35) FILENAME color(36) ":" color(32) FNR color(36) ":" color(0) $0; }; function color(c) { return "\033[" c "m"; }'
      【解决方案7】:

      有点老了,不过还好……

      @houbysoft 投票最多的解决方案将不起作用,因为它会排除任何带有“gloom”的行,即使它有“loom”。根据 OP 的预期,我们需要包含带有“loom”的行,即使它们也有“gloom”。此行需要在输出“Arty is slooming in a glomy day.”中,但这将被像

      这样的链式 grep 排除在外
      grep -n 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp) | grep -v 'gloom'
      

      相反,Bentoy13 的 egrep regex 示例效果更好

      egrep '(^|[^g])loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
      

      因为它将包含任何带有“loom”的行,无论它是否有“gloom”。另一方面,如果它只有阴暗,它不会包含它,这正是OP想要的行为。

      【讨论】:

        【解决方案8】:

        问题:搜索“loom”,不包括“gloom”。
        答:

        grep -w 'loom' ~/projects/**/trunk/src/**/*.@(h|cpp)
        

        【讨论】:

        • 来自问题:所以,例如,我在命令输出中需要bloomberg,不需要ungloomy。 我不认为@ 987654324@ 是解决这个难题的方法。
        【解决方案9】:

        -v 是“反向匹配”标志,所以管道是一个非常好的方法:

        grep "loom" ~/projects/**/trunk/src/**/*.@(h|cpp)| grep -v "gloom"

        【讨论】:

          【解决方案10】:

          只需使用! grep -v 多次。

          文件内容

          [root@server]# cat file
          1
          2
          3
          4
          5
          

          排除行或匹配

          [root@server]# cat file |grep -v 3
          1
          2
          4
          5
          

          排除该行或匹配多个

          [root@server]# cat file |grep -v 3 |grep -v 5
          1
          2
          4
          

          【讨论】:

          • 是的,但是您如何遍历一组相似的文件。如果我想检查 1000 个文件,我不想运行此命令 1000 次
          猜你喜欢
          • 1970-01-01
          • 2023-04-01
          • 2014-07-30
          • 1970-01-01
          • 2014-09-10
          • 1970-01-01
          • 2014-02-28
          • 2011-05-31
          • 2018-08-05
          相关资源
          最近更新 更多