Como pesquisar ocorrência de uma palavra e ausência de outra usando grep

Como pesquisar ocorrência de uma palavra e ausência de outra usando grep

Eu tenho um arquivo com conteúdo semelhante a:

google.com,9,AB+CD,nonAB+nonCD
youtube.com,9,AB+CD,AB+CD
facebook.com,20,AB+CD,nonCD

O número de colunas não é fixo. Mas a primeira coluna é um URL, a segunda é um número, começando pela terceira são palavras-chave separadas por vírgulas, mas variam de site para outro.

Quero contar o número de URLs (linhas) onde posso controlar quais palavras-chave estão na linha. Por exemplo,
1) AB+CDsem nonABe nonCD. Nota: a palavra AB+CD pode ocorrer muitas vezes. 2) AB+CD sem ocorrência de nonCD(mas tudo bem se houver mais alguma coisa)

Como procurar uma string em uma linha E garantir a ausência de outra string. Quando eu uso:

grep 'AB+CD' test.txt > result.txt

Ele imprime todas as linhas onde 'AB+CD' é encontrado.

E se eu quiser imprimir a linha onde existe apenas 'AB+CD' para obter:

youtube.com,9,AB+CD,AB+CD

Ou existe 'AB+CD' com qualquer outra coisa exceto 'nonAB' para obter:

youtube.com,9,AB+CD,AB+CD
facebook.com,20,AB+CD,nonCD

Responder1

Se você deseja apenas uma pesquisa de texto simples sem se preocupar com colunas, você pode encadear a correspondência invertida grep -vda seguinte forma:

cat input.txt | grep 'IncludedText' | grep -v 'ExcludedText'

Se você quiser fazer uma filtragem adequada por coluna, use algo como awk.

Responder2

Truques gerais:

  1. Linhas contendo foomais linhas contendo bar( foo OR bar):

    grep -e foo -e bar
    
  2. Linhas contendo fooe barna mesma linha ( foo AND bar):

    grep foo | grep bar
    
  3. Linhas que não contêm baz( NOT baz):

    grep -v baz
    

Com esses tijolos você pode construir sua lógica. O problema -vnão está restrito a um único padrão, é global para todo grep(pelo menos no meu Debian). Isto torna NOT (foo OR bar)possível:

grep -v -e foo -e bar

que é equivalente a (NOT foo) AND (NOT bar):

grep -v foo | grep -v bar

No entanto NOT (foo AND bar)(logicamente equivalente a (NOT foo) OR (NOT bar)) não é tão fácil. Podemos tentar obter foo AND barcom umsolteiro(estendido) grep:

  1. Novamente linhas contendo fooe barna mesma linha ( foo AND bar):

    grep -E 'foo.*bar|bar.*foo'
    

Agora para obter NOT (foo AND bar):

grep -v -E 'foo.*bar|bar.*foo'

Não tenho certeza se o sistema acima é um sistema completo ao lidar com mais de dois padrões. Ainda poucos dos seus problemas podem ser resolvidos com isso. Exemplo:

AB+CDsem nonABenonCD

Se eu te acertar, éAB+CD AND NOT (nonAB OR nonCD)

grep AB+CD | grep -v -e nonAB -e nonCD

Observe que esta solicitação complica as coisas:

Quero imprimir a linha onde só existe 'AB+CD'

Pode-se dizer grep ,AB+CD,AB+CDque sim, mas como "o número de colunas não é fixo", acho que você gostaria de distinguir essas duas linhas:

youtube.com,9,AB+CD,AB+CD,AB+CD
youtube.com,9,AB+CD,AB+CD,banana

Nesses casos, você precisa de expressões regulares mais complicadas ou de outras ferramentas (como awk).

Responder3

Embora você obtenha a resposta aqui, você deve dar uma olhada emhomem grep(pode ser opressor) ealguns exemplos. Por enquanto, aqui vai a resposta:

Usandogrep

grep "foobar" test.txt

irá procurar por linhas contendo palavras foobarno arquivo test.txte exibir todas as ocorrências enquanto,

grep "foo" -v "bar" test.txt

irá procurar por linhas que contenham word, foomas não bar. Conseguimos isso por causa-vswitch para qual página de manual explica:

-v, --invert-match
    Invert the sense of matching, to select non-matching lines.
    (-v is specified by POSIX .)

Significa simplesmente que irá procurar por linhas que contenham essas palavras (aqui bar), mas as excluirá na exibição final. Por issoinvertendo a busca.

Além disso, para contar o número de linhas que correspondem à pesquisa, use-ctrocar :

-c, --count
    Suppress normal output; instead print a count of matching lines
    for each input file. With the -v, --invert-match option (see below),
    count non-matching lines. (-c is specified by POSIX .)

Como um auto-exercício, experimente a pesquisa grep no arquivofoobar.

A resposta

Pesquise por AB+CDignorar nonABe nonCDcontar URLs:

grep "AB+CD" test | grep -cve "non"

onde -v "non"simplesmente ignorará ambos nonABe nonCDcomo ambos contêm non. E -cdará a contagem total das partidas em vez de imprimi-las. Para imprimir linhas correspondentes, simplesmente ignore -c.

Você pode usá-lo para inversões separadas:

grep "AB+CD" test | grep -cve "nonAB\|nonCD"

onde \|representa ORe significa um de nonABounonCD exatopalavra especificada por-etrocar.


Aconselharia você aveja a resposta de Kamil, leia as páginas de manual (você conhece o comando) o máximo que puder, tente ao máximo enquanto pesquisa coisas online e sirva a comunidade. Sinta-se à vontade para adicionar mais detalhes para responder.

informação relacionada