【问题标题】:How can I exclude one word with grep?如何用 grep 排除一个单词?
【发布时间】:2011-05-31 02:38:18
【问题描述】:

我需要类似的东西:

grep ^"unwanted_word"XXXXXXXX

【问题讨论】:

  • grep -Rv "word_to_be_ignored" . | grep "word_to_be_searched"

标签: regex string search grep


【解决方案1】:

您可以使用 grep 的 -v (for --invert-match) 选项作为:

grep -v "unwanted_word" file | grep XXXXXXXX

grep -v "unwanted_word" file 将过滤具有unwanted_word 的行,grep XXXXXXXX 将仅列出模式为XXXXXXXX 的行。

编辑:

从您的评论看来,您想列出所有没有unwanted_word 的行。在这种情况下,您只需要:

grep -v 'unwanted_word' file

【讨论】:

  • 如果我想在“不需要的单词”行之后排除 N 行怎么办? -v 'unwanted_word' --after N 没有帮助,因为它包括该行和之后的 N 行。
  • -v--invert-match 选择不匹配的行。在你的情况下grep -v 'unwanted_word' filegrep --invert-match 'unwanted_word' file
  • 我想用匹配的模式忽略上面一行和下面一行,那么我该如何实现呢?
  • 奇怪,这是最佳答案,但在某些情况下它是错误的!如果我想找到sun,除非是sunrisegrep sun|grep -v sunrise 会同时跳过包含sunsunrise 的行,这不是我想要的。 grep -P 'sun(?!rise)' 好多了。
  • 如果你想将正则表达式的力量带入排除模式,只需添加-E。例如grep -v -E "unwanted_pattern_in_regex" file
【解决方案2】:

我将问题理解为“如何匹配一个单词但排除另一个单词”,其中一个解决方案是串联两个 grep:第一个 grep 找到想要的“word1”,第二个 grep 排除“word2”:

grep "word1" | grep -v "word2"

在我的情况下:我需要区分“plot”和“#plot”,而 grep 的“word”选项不会这样做(“#”不是字母数字)。

希望这会有所帮助。

【讨论】:

  • 您应该颠倒顺序以突出显示word1
  • 我想它会澄清为该示例添加文件名的占位符
  • @MatthewRead 我发现它真的更像这样的逻辑。首先,您要查找“word1”的出现,然后删除在也有“word2”的地方发现的出现。相反的情况很奇怪:首先删除“word2”,然后查找您想要的单词。也许这只是一个观点
  • @Nico 不过,在找到更有用的东西后,没有理由继续坚持最初的冲动。如果您经常使用它,我建议您创建一个可以调用的 shell 函数(例如 xnoty() { grep -v "$2" | grep "$1" }),这样您就不必记住构造。
【解决方案3】:

如果您的grep 支持带有-P 选项的Perl 正则表达式,您可以这样做(如果是bash;如果是tcsh,您需要转义!):

grep -P '(?!.*unwanted_word)keyword' file

演示:

$ cat file
foo1
foo2
foo3
foo4
bar
baz

现在让我们列出除foo3 之外的所有foo

$ grep -P '(?!.*foo3)foo' file
foo1
foo2
foo4
$ 

【讨论】:

  • 感谢,非常有用!我想提一下,grep 命令默认区分大小写
  • 请注意,grep -v -P 在正则表达式中也可以在没有否定的情况下工作。
  • "如果 bash...你需要转义 !"。谢谢你,谢谢你,谢谢你!这就是我想要的!
  • 但是,这在 `grep -P '(?!.*foo3)[a-zA-Z0-9]*' 模式下不起作用,它不会找到什么你想省略,但只会找到确切的东西,所以正则表达式对于精确的短语没什么用
  • 建议的模式(?!.*unwanted_word)keyword 仅排除unwanted_word 开始 keyword 之后的行(可能重叠)。要排除包含unwanted_word任何 行,无论其相对于keyword 的位置如何,请使用^(?!.*unwanted_word).*\Kkeyword
【解决方案4】:

正确的解决方案是使用grep -v "word" file,与awk 等效:

awk '!/word/' file

但是,如果您碰巧遇到更复杂的情况,例如,您希望出现 XXXYYY 出现,那么 awk 会派上用场,而不是管道几个greps:

awk '/XXX/ && !/YYY/' file
#    ^^^^^    ^^^^^^
# I want it      |
#            I don't want it

你甚至可以说一些更复杂的东西。例如:我想要那些包含XXXYYY 的行,但不包含ZZZ

awk '(/XXX/ || /YYY/) && !/ZZZ/' file

等等

【讨论】:

  • 它似乎比 grep -P 解决大文件要快得多。
  • @MBR grep -P 表示使用 Perl 正则表达式,因此加载该软件包将比普通的 grep 更昂贵。
【解决方案5】:

使用 grep -v 反转匹配:

grep -v "unwanted word" file pattern

【讨论】:

    【解决方案6】:

    grep 提供 '-v' 或 '--invert-match' 选项来选择不匹配的行。

    例如

    grep -v 'unwanted_pattern' file_name
    

    这将输出文件 file_name 中没有“unwanted_pa​​ttern”的所有行。

    如果您在文件夹内的多个文件中搜索模式,您可以使用递归搜索选项,如下所示

    grep -r 'wanted_pattern' * | grep -v 'unwanted_pattern'
    

    这里 grep 将尝试列出当前目录中所有文件中出现的所有“wanted_pa​​ttern”,并将其传递给第二个 grep 以过滤掉“unwanted_pa​​ttern”。 '|' - 管道将告诉 shell 将左侧程序的标准输出 (grep -r 'wanted_pa​​ttern' *) 连接到右侧程序的标准输入 (grep -v 'unwanted_pa​​ttern')。

    【讨论】:

      【解决方案7】:

      -v 选项将显示所有与模式不匹配的行。

      grep -v ^unwanted_word
      

      【讨论】:

        【解决方案8】:

        我使用grep -vw "^/" 排除了根(“/”)挂载点。

        # cat /tmp/topfsfind.txt| head -4 |awk '{print $NF}'
        /
        /root/.m2
        /root
        /var
        
        # cat /tmp/topfsfind.txt| head -4 |awk '{print $NF}' | grep -vw "^/"
        /root/.m2
        /root
        /var
        

        【讨论】:

          【解决方案9】:

          我有一个包含一堆文件的目录。我想找到所有不包含字符串“speedup”的文件,所以我成功使用了以下命令:

          grep -iL speedup *
          

          【讨论】:

          • 来自手册页:“-L, --files-without-match 禁止正常输出;而是打印通常不会打印输出的每个输入文件的名称。扫描将在第一场比赛停止。“(我强调)所以要小心这个!
          猜你喜欢
          • 1970-01-01
          • 2011-02-22
          • 1970-01-01
          • 1970-01-01
          • 2012-07-25
          • 2018-12-13
          • 1970-01-01
          • 2013-08-30
          • 1970-01-01
          相关资源
          最近更新 更多