Com o GNU awk
:
$ printf '%s\n' {foo,bar}{bar,foo} neither | gawk 'xor(/foo/,/bar/)'
foofoo
barbar
Ou portably:
awk '((/foo/) + (/bar/)) % 2'
Com um grep
suporte para -P
(PCRE):
grep -P '^((?=.*foo)(?!.*bar)|(?=.*bar)(?!.*foo))'
Com sed
:
sed '
/foo/{
/bar/d
b
}
/bar/!d'
Se você considerar apenas palavras inteiras (que não é nem foo
nem bar
em foobar
ou barbar
por exemplo), você precisa decidir como essas palavras são delimitados. Se for por qualquer caractere que não seja letras, dígitos e sublinhado, como a -w
opção de muitas grep
implementações, altere-os para:
gawk 'xor(/\<foo\>/,/\<bar\>/)'
awk '((/(^|[^[:alnum:]_)foo([^[:alnum:]_]|$)/) + \
(/(^|[^[:alnum:]_)bar([^[:alnum:]_]|$)/)) % 2'
grep -P '^((?=.*\bfoo\b)(?!.*\bbar\b)|(?=.*\bbar\b)(?!.*\bfoo\b))'
Por sed
que se torna um pouco complicado se não tiver uma sed
aplicação como o GNU sed
que suporta \<
/ \>
como limites da palavra como o GNU awk
faz.