Con GNU awk
:
$ printf '%s\n' {foo,bar}{bar,foo} neither | gawk 'xor(/foo/,/bar/)'
foofoo
barbar
O portablemente:
awk '((/foo/) + (/bar/)) % 2'
Con un grep
soporte para -P
(PCRE):
grep -P '^((?=.*foo)(?!.*bar)|(?=.*bar)(?!.*foo))'
Con sed
:
sed '
/foo/{
/bar/d
b
}
/bar/!d'
Si desea considerar solo palabras completas (que no hay foo
ni bar
en foobar
ni barbar
por ejemplo), deberá decidir cómo se delimitan esas palabras. Si es por cualquier carácter que no sean letras, dígitos y guiones bajos, como lo hace la -w
opción de muchas grep
implementaciones, entonces los cambiaría a:
gawk 'xor(/\<foo\>/,/\<bar\>/)'
awk '((/(^|[^[:alnum:]_)foo([^[:alnum:]_]|$)/) + \
(/(^|[^[:alnum:]_)bar([^[:alnum:]_]|$)/)) % 2'
grep -P '^((?=.*\bfoo\b)(?!.*\bbar\b)|(?=.*\bbar\b)(?!.*\bfoo\b))'
Para sed
eso se vuelve un poco complicado a menos que tenga una sed
implementación como GNU sed
que admita \<
/ \>
como límites de palabras como lo awk
hace GNU .