![如何 grep 查找包含两个单词之一但不是同时包含两个单词的行?](https://linux22.com/image/147263/%E5%A6%82%E4%BD%95%20grep%20%E6%9F%A5%E6%89%BE%E5%8C%85%E5%90%AB%E4%B8%A4%E4%B8%AA%E5%8D%95%E8%AF%8D%E4%B9%8B%E4%B8%80%E4%BD%86%E4%B8%8D%E6%98%AF%E5%90%8C%E6%97%B6%E5%8C%85%E5%90%AB%E4%B8%A4%E4%B8%AA%E5%8D%95%E8%AF%8D%E7%9A%84%E8%A1%8C%EF%BC%9F.png)
我试图用来grep
仅显示包含这两个单词中的任何一个的行,如果它们中只有一个出现在行中,但如果它们在同一行中则不显示。
到目前为止,我已经尝试过, grep pattern1 | grep pattern2 | ...
但没有得到我预期的结果。
答案1
除此以外的工具grep
才是出路。
例如,使用 perl,命令将是:
perl -ne 'print if /pattern1/ xor /pattern2/'
perl -ne
运行对 stdin 的每一行给出的命令,在本例中,如果匹配 ,则打印该行/pattern1/ xor /pattern2/
,或者换句话说,匹配一个模式但不匹配另一个模式(异或)。
这适用于任一顺序的模式,并且应该比多次调用 , 具有更好的性能grep
,并且打字也更少。
或者,更短,使用 awk:
awk 'xor(/pattern1/,/pattern2/)'
或者对于没有的 awk 版本xor
:
awk '/pattern1/+/pattern2/==1`
答案2
使用 GNU grep
,您可以将两个单词传递给grep
然后删除包含这两个模式的行。
$ cat testfile.txt
abc
def
abc def
abc 123 def
1234
5678
1234 def abc
def abc
$ grep -w -e 'abc' -e 'def' testfile.txt | grep -v -e 'abc.*def' -e 'def.*abc'
abc
def
答案3
尝试用egrep
egrep 'pattern1|pattern2' file | grep -v -e 'pattern1.*pattern2' -e 'pattern2.*pattern1'
答案4
用布尔术语来说,您正在寻找 A xor B,它可以写为
(A 而不是 B)
或者
(B 而不是 A)
鉴于您的问题没有提到您关心输出的顺序,只要显示匹配行,A xor B 的布尔扩展在 grep 中就非常简单:
$ cat << EOF > foo
> a b
> a
> b
> c a
> c b
> b a
> b c
> EOF
$ grep -w 'a' foo | grep -vw 'b'; grep -w 'b' foo | grep -vw 'a';
a
c a
b
c b
b c