С GNU awk
:
$ printf '%s\n' {foo,bar}{bar,foo} neither | gawk 'xor(/foo/,/bar/)'
foofoo
barbar
Или переносимо:
awk '((/foo/) + (/bar/)) % 2'
С grep
поддержкой -P
(PCRE):
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 , sed
которая поддерживает \<
/ , \>
как границы слов , как GNU awk
делает.