grep com operadores lógicos

16

Existe um utilitário semelhante ao grep que me permitirá fazer buscas no grep com operadores lógicos? Eu quero ser capaz de aninhar e combinar as construções lógicas livremente. Por exemplo, coisas como essa devem ser possíveis:

grep (term1 && term2) || (term1 && (term3 xor term4)) *

Sei que isso pode ser feito com vanilla grep e script adicional de bash, mas meu objetivo aqui é evitar ter que fazer isso.

    
por Nikita Kiryanov 05.01.2015 / 12:21

5 respostas

12

Com awk , como em perl , você terá que agrupar os termos em // , mas isso pode ser feito:

awk '(/term1/ && /term2/) || (/term1/ && xor(/term3/, /term4/))' 
    
por 05.01.2015 / 13:31
24

Existem várias maneiras de usar grep com operadores lógicos.

  1. Use \| para separar vários padrões para a condição OR .

    Exemplo: grep 'pattern1\|pattern2' filename

  2. Use a opção -E para enviar vários padrões para o OR condição.

    Exemplo: grep -E 'pattern1|pattern2' filename

  3. Usar um único -e corresponde apenas a um padrão, mas usando vários A opção -e corresponde a mais de um padrão.

    Exemplo: grep -e pattern1 -e pattern2 filename

  4. grep -v pode simular a operação NOT .

  5. Não há nenhum operador AND em grep , mas você pode usar a força bruta simule AND usando a opção -E .

    Exemplo: grep -E 'pattern1.*pattern2|pattern2.*pattern1' filename

    O exemplo acima irá corresponder a todas as linhas que contenham pattern1 e pattern2 em qualquer ordem.

por 05.01.2015 / 13:12
5

Você pode usar o perl:

perl -wne 'print if (/term1/ && /term2/) || (/term1/ && (/term3/ xor /term4/))'
    
por 05.01.2015 / 12:49
1

Eu uso para encadear comandos grep para obter um AND lógico:

grep expr1 filename | grep expr2

Eu acredito que é bem direto, parecido com o Unix e elegante.

Então você pode combinar (como explicado pelo @Tushi) com a opção -E para OR e -v para negação.

Seu exemplo específico é bastante desagradável e provavelmente se beneficiaria de algum utilitário mais poderoso (veja a resposta de @ muru).

    
por 04.10.2018 / 10:02
0
sed '/term1/!d;/term2/b' -e '/term3/!d;/term4/d' *

Eu acredito que realiza o que você está tentando fazer. Ele d elimina da saída qualquer linha que não corresponda a term1 , ele b sai do script (e, assim, autoprints) qualquer linha que permaneça e corresponda a term2 , e para as linhas que permanecem exclui as que não corresponderem a term3 e daquelas que corresponderem a term4 .

sed scripts são avaliados em ordem, e todos os testes são booleanos, portanto, quaisquer ações resultantes de um teste afetarão diretamente o comportamento de quaisquer ações a seguir.

    
por 05.01.2015 / 18:24

Tags