Como posso encontrar todas as linhas contendo duas palavras especificadas? [duplicado]

5

Eu preciso verificar se existem duas palavras (especificadas) em qualquer linha de um arquivo de texto. Não há limites para os caracteres das palavras. Por exemplo:

Eu quero encontrar linhas de um arquivo de texto que contenham as duas palavras "gato" e "elefante" juntas (ou seja, na mesma linha; não necessariamente lado-a-lado):

Cat is smaller than elephant
Elephant is larger than cat
Cats are cute!
Elephants are very strong
Cat and elephants live in different environments
cats are friendly

Nos exemplos anteriores, como posso encontrar as linhas contendo as duas palavras?

Cat is smaller than elephant
Elephant is larger than cat
Cat and elephants live in different environments

Eu tentei grep e awk sem esperança. O problema é que há palavras que têm letras maiúsculas e minúsculas, então, como eu posso combinar para ambas as palavras, independentemente do status das letras!?

    
por G-Man 17.10.2018 / 00:13

4 respostas

7

com grep

grep -i "cat" file | grep -i "elephant"

Cat is smaller than elephant
Elephant is larger than cat
Cat and elephants live in different environment

O sinalizador em grep é para ignorar maiúsculas e minúsculas (superior / inferior)

 -i, --ignore-case         ignore case distinctions

ou awk

awk 'BEGIN{IGNORECASE=1} /cat/&&/elephant/{print $0}' file

@glenn jackman sugeriu que a instrução awk possa ser executada da seguinte forma:

awk '/cat/&&/elephant/' IGNORECASE=1 file
    
por 17.10.2018 / 00:20
6
$ grep -Fiw cat <file | grep -Fiw elephant
Cat is smaller than elephant
Elephant is larger than cat

Primeiramente, extraímos todas as linhas do arquivo file que contém a palavra cat e, em seguida, restringimos essas linhas àquelas que contêm a palavra elephant .

Isso é feito usando grep -F -i -w , onde

  • -F faz grep tratar o padrão como uma string fixa, não como uma expressão regular,
  • -i torna grep a correspondência insensível a maiúsculas e
  • -w faz com que grep corresponda apenas a palavras completas.

A opção -w é uma extensão do padrão POSIX para grep , mas é implementado pelas implementações mais comuns de grep . Basicamente, ele impede as correspondências do patten dado quando a string correspondente faz parte de uma palavra mais longa.

Note que não estou combinando com a linha

Cat and elephants live in different environment

Isso ocorre devido ao s final em elephants . Eu também não combinaria com a linha

elephantiasis is catastrophic

pelo mesmo motivo.

Você deseja permitir um s no final das palavras, use

$ grep -Eiw 'cats?' <file | grep -Eiw 'elephants?'
Cat is smaller than elephant
Elephant is larger than cat
Cat and elephants live in different environment

Aqui, usamos uma expressão regular (estendida) em vez de uma string fixa em ambas as invocações de grep . As expressões corresponderão a um s opcional no final das duas palavras. Agora, correspondemos cat e cats (sem distinção entre maiúsculas e minúsculas), mas não corresponderia a catnip , catsup ou scat .

    
por 17.10.2018 / 07:41
3

com o GNU sed:

sed -n '/cat/I {/elephant/I p}' file

ou perl

perl -ne 'print if /cat/i and /elephant/i' file

ou um único grep

grep -i -e 'cat.*elephant' -e 'elephant.*cat' file
    
por 17.10.2018 / 03:56
2

Você pode fazer isso em não-GNU awk usando o truque do "homem pobre" para obter insensibilidade a maiúsculas e minúsculas:

awk  '/[Cc][Aa][Tt]/ && /[Ee][Ll][Ee][Pp][Hh][Aa][Nn][Tt]/'  file
onde, assim como [aeiou] corresponde a qualquer um dos a , e , i , o ou u , [Ee] corresponde a E ou e - ou seja, uma correspondência sem distinção entre maiúsculas e minúscula para "e".

Note que esta abordagem (como todas as outras respostas postadas aqui até agora) irá coincidir com a linha

There are many ways to catch an elephant.
porque a palavra “ cat ch” contém a string “cat”. Se você quiser evitar isso, tente
awk  '/(^|\W)[Cc][Aa]Tt/ && /(^|\W)[Ee][Ll][Ee][Pp][Hh][Aa][Nn]Tt/'  file
onde você restringe cada palavra para ser precedido por um caractere sem palavra (ou o início da linha) e seguido por um caractere sem palavra (ou o fim da linha) - \W corresponde a um caractere não pertencente à palavra (isto é, um espaço (ou tabulação) ou outro caractere * não alfanumérico.

(não tenho certeza se isso é compatível com POSIX).

Observe que isso agora não será

Cat and elephants live in different environments
porque a palavra "elefantes" não é a mesma que a palavra "elefante".
por 17.10.2018 / 07:11