过滤不包含在列表中的行

时间:2014-04-20 06:27:34

标签: regex linux bash shell unix

当我过滤不包含指定字符串的行时,我使用 grep -v "specifiedstring" filename 但是如何过滤列表中不包含多个字符串的行。 非常感谢!

3 个答案:

答案 0 :(得分:3)

您可以or多个字符串:

grep -v "string1\|string2\|string3" filename

这会排除包含string1string2string3的行。

在基本的正则表达式(上面的版本)中,正则表达式元字符失去了它们的特殊含义,需要被转义。

使用扩展正则表达式,您无需转义|

grep -Ev "string1|string2|string3" filename

如果列表包含在文件中,请使用-f选项:

grep -v -f list_to_exclude filename

如评论中所述,如果模式是一组字符串,则可以提供-F选项以加快grep

grep -F -v -f list_to_exclude filename

从手册:

   -F, --fixed-strings
          Interpret PATTERN as a  list  of  fixed  strings,  separated  by
          newlines,  any  of  which is to be matched.  (-F is specified by
          POSIX.)

以下示例应进一步解释。给定一个输入文件,比如input.txt

This is line.
This is line2.
This is line3.
This is line4.
This is line*.

现在使用命令:

grep -v 'line*' input.txt

不会产生任何结果,因为模式 line*被解释为正则表达式并且将匹配给定输入文件中的所有行并且-v反转匹配。如果line*固定字符串而不是正则表达式,那么提供-F选项,即说:

grep -F -v 'line*' input.txt

会产生:

This is line.
This is line2.
This is line3.
This is line4.

此外,由于grep现在不寻找模式,但对于固定字符串,它比没有使用-F选项要快得多。

答案 1 :(得分:3)

您可以使用grep

AND多个字符串
grep -v "string1.*string2" file 

这会过滤掉包含string1和string2的行,同时留下只包含string1或string2的行

答案 2 :(得分:1)

如果您从其他命令获取列表而不是文件:

grep -F -v -f <(get_list_to_exclude) <(get_list_to_filter)
  

注意:如果排除输出为空, grep会失败(因为一个空行与过滤列表中的任何一行匹配)。

如果列表已排序,则可以使用comm实用程序。使用空排除列表 不会失败。

  

comm - 选择或拒绝两个文件共有的行

两个示例文件:

$ cat a
a
b
c
$ cat b
a
z

comm可以按以下方式过滤列表:

# exclude b from a
$ comm -2 -3 a b
b
c


# exclude a from b
$ comm -1 -3 a b
z

stream的语法相同:

$ comm -2 -3 <(cat a) <(cat b)
b
c

请参阅man comm了解更多说明。

翻译自StackOverflow in Russian