Estou tentando usar grep
para mostrar apenas linhas contendo uma das duas palavras, se apenas uma delas aparecer na linha, mas não se elas estiverem na mesma linha.
Até agora, tentei, grep pattern1 | grep pattern2 | ...
mas não obtive o resultado esperado.
[a-z][a-z0-9]\(,7\}\(\.[a-z0-9]\{,3\}\)+
? (2) E se uma das palavras / padrões aparecer mais de uma vez em uma linha (e a outra não aparecer)? Isso é equivalente à palavra que aparece uma vez ou conta como várias ocorrências?Respostas:
Uma ferramenta que não
grep
é o caminho a percorrer.Usando perl, por exemplo, o comando seria:
perl -ne
executa o comando fornecido sobre cada linha de stdin, que nesse caso imprime a linha se corresponder/pattern1/ xor /pattern2/
ou, em outras palavras, corresponde a um padrão, mas não ao outro (exclusivo ou).Isso funciona para o padrão em qualquer ordem e deve ter um desempenho melhor do que várias invocações
grep
e também é menos digitado.Ou, ainda mais curto, com awk:
ou para versões do awk que não possuem
xor
:fonte
xor
disponível apenas no GNU Awk?/pattern1/+/pattern2/==1
irxor
está ausente.\b
) nos próprios padrões, ie\bword\b
.Com o GNU
grep
, você pode passar as duas palavrasgrep
e remover as linhas que contêm os dois padrões.fonte
Tente com
egrep
fonte
grep -e foo -e bar | grep -v -e 'foo.*bar' -e 'bar.*foo'
Direct invocation as either egrep or fgrep is deprecated
- prefiragrep -E
-f
e-e
opções, embora seja antigoegrep
efgrep
continuará sendo suportado por um tempo.grep
(ou suportes-F
,-E
,-e
,-f
como exige POSIX) é em/usr/xpg4/bin
. Os utilitários/bin
são antiquados.Com
grep
implementações que suportam expressões regulares do tipo perl (comopcregrep
ou GNU ou ast-opengrep -P
), você pode fazer isso em umagrep
chamada com:Ou seja, encontrar as linhas que correspondem,
pat1
mas nãopat2
, oupat2
mas nãopat1
.(?=...)
e,(?!...)
respectivamente, são operadores de antecipação e negativo. Portanto, tecnicamente, o item acima procura o início do assunto (^
), desde que seja seguido.*pat1
e não seguido por.*pat2
, ou o mesmo compat1
epat2
invertido.Isso é subótimo para linhas que contêm os dois padrões, pois seriam procurados duas vezes. Você poderia usar operadores perl mais avançados, como:
(?(1)yespattern|nopattern)
corresponde contrayespattern
se o grupo de captura1
st (vazio()
acima) corresponder, ounopattern
não. Se esse()
partidas, isso significa quepat1
não se encontraram, então olhamos parapat2
(olhar positivo à frente), e nós olhamos para nãopat2
o contrário (em frente olhar negativo).Com
sed
, você pode escrever:fonte
grep: the -P option only supports a single pattern
, pelo menos em todos os sistemas aos quais tenho acesso. +1 para sua segunda solução, no entanto.grep
.pcregrep
e o ast-open grep não tem esse problema. Substituí o múltiplo-e
pelo operador RE alternativo, portanto, ele deve funcionar com o GNUgrep
também agora.Em termos booleanos, você está procurando A xor B, que pode ser escrito como
(A e não B)
ou
(B e não A)
Dado que sua pergunta não menciona que você está preocupado com a ordem da saída, desde que as linhas correspondentes sejam mostradas, a expansão booleana de A xor B é bastante simples no grep:
fonte
sort | uniq
.Para o seguinte exemplo:
Isso pode ser feito puramente com
grep -E
,uniq
ewc
.Se
grep
for compilado com expressões regulares do Perl, você poderá corresponder na última ocorrência, em vez de precisar canalizar parauniq
:Saída do resultado:
Uma linha:
Se você não deseja codificar o padrão, montá-lo com um conjunto variável de elementos pode ser automatizado com uma função.
Isso também pode ser feito de forma nativa no Bash como uma função sem canais ou processos adicionais, mas estaria mais envolvido e provavelmente está fora do escopo da sua pergunta.
fonte
Big apple\n
epear-shaped\n
, a saída deverá conter as duas linhas. Sua solução receberá uma contagem de 2; a versão longa informaria "Ambas as palavras correspondiam" (que é uma resposta à pergunta errada) e a versão curta não dizia nada. (3) Uma sugestão: usar-o
aqui é uma péssima idéia, porque oculta as linhas que contêm as correspondências, portanto você não pode ver quando as duas palavras aparecem na mesma linha. … (Continua)uniq
/sort -u
e a expressão regular sofisticada de Perl para corresponder apenas à última ocorrência em cada linha não são realmente uma resposta útil para esta pergunta. Mas, mesmo se o fizessem, ainda seria uma resposta ruim, porque você não explica como eles contribuem para responder à pergunta. (Veja a resposta de Stéphane Chazelas para um exemplo de uma boa explicação.)