我想在文本文件中搜索带有“word1”XOR“word2”的行。因此它应该输出包含 word1、word2 的行,但不输出包含这两个单词的行。我想使用 XOR,但我不知道如何在 Linux 命令行中编写它。
我试过:
grep 'word1\|word2' text.txt
grep word1 word2 text.txt
grep word1 text.txt | grep word2
grep 'word1\^word2' text.txt
等等,但都未能成功。
答案1
使用 GNU awk
:
$ printf '%s\n' {foo,bar}{bar,foo} neither | gawk 'xor(/foo/,/bar/)'
foofoo
barbar
或者便携式:
awk '((/foo/) + (/bar/)) % 2'
支持( grep
PCRE -P
):
grep -P '^((?=.*foo)(?!.*bar)|(?=.*bar)(?!.*foo))'
和sed
:
sed '
/foo/{
/bar/d
b
}
/bar/!d'
如果您只想考虑整个单词(例如既没有foo
也没有bar
在foobar
或barbar
中),您需要决定如何分隔这些单词。如果它是由除字母、数字和下划线之外的任何字符组成的,就像-w
许多grep
实现的选项一样,那么您可以将它们更改为:
gawk 'xor(/\<foo\>/,/\<bar\>/)'
awk '((/(^|[^[:alnum:]_)foo([^[:alnum:]_]|$)/) + \
(/(^|[^[:alnum:]_)bar([^[:alnum:]_]|$)/)) % 2'
grep -P '^((?=.*\bfoo\b)(?!.*\bbar\b)|(?=.*\bbar\b)(?!.*\bfoo\b))'
因为sed
这会变得有点复杂,除非你有sed
像 GNU 这样的实现,像 GNU 一样sed
支持\<
/\>
作为字边界awk
。
答案2
grep 'word1\|word2' text.txt
搜索包含word1
或 的行word2
。这包括同时包含两者的行。
grep word1 text.txt | grep word2
搜索包含word1
和 的行word2
。这两个词可以重叠(例如foobar
containsfoo
和ob
)。搜索包含两个单词的行的另一种方法(但仅以不重叠的方式)是按任一顺序搜索它们:grep 'word1.*word2\|word2.*word1' text.txt
grep word1 text.txt | grep -v word2
搜索包含word1
但不包含 的行word2
。该-v
选项告诉 grep 保留不匹配的行并删除匹配的行,而不是相反。这将为您提供所需结果的一半。通过添加对称搜索,您可以获得恰好包含某个单词的所有行。
grep word1 text.txt | grep -v word2
grep word2 text.txt | grep -v word1
或者,您可以从包含任一单词的行开始,然后删除包含这两个单词的行。考虑到上面的构建块,如果单词不重叠,这很容易。
grep 'word1\|word2' text.txt | grep -v 'word1.*word2\|word2.*word1'
答案3
bash 解决方案:
#!/bin/bash
while (( $# )); do
a=0 ; [[ $1 =~ foo ]] && a=1
b=0 ; [[ $1 =~ bar ]] && b=1
(( a ^ b )) && echo "$1"
shift
done
要测试它:
$ ./script {foo,bar}\ {foo,bar} neither
foo foo
bar bar