Eu tenho tentado encontrar uma maneira de filtrar uma linha que contenha a palavra "limão" e "arroz". Eu sei como encontrar "limão" ou "arroz", mas não os dois. Eles não precisam estar próximos um do outro, apenas um na mesma linha de texto.
Eu tenho tentado encontrar uma maneira de filtrar uma linha que contenha a palavra "limão" e "arroz". Eu sei como encontrar "limão" ou "arroz", mas não os dois. Eles não precisam estar próximos um do outro, apenas um na mesma linha de texto.
Respostas:
"Ambos na mesma linha" significam "'arroz' seguido de caracteres aleatórios seguidos de 'limão' ou o contrário".
Em regex que é rice.*lemon
ou lemon.*rice
. Você pode combinar isso usando um |
:
grep -E 'rice.*lemon|lemon.*rice' some_file
Se você deseja usar regex normal em vez de estendidos ( -E
), precisará de uma barra invertida antes de |
:
grep 'rice.*lemon\|lemon.*rice' some_file
Para mais palavras que rapidamente se tornam um pouco mais longas e geralmente é mais fácil usar várias chamadas grep
, por exemplo:
grep rice some_file | grep lemon | grep chicken
grep rice
encontra as linhas que contêm rice
. Ele é alimentado no grep lemon
qual somente serão encontradas linhas contendo limão ... e assim por diante. Considerando que o OP -, bem como as suas respostas anteriores - estão permitindo que qualquer de [arroz | limão | frango]
|
precisa ser evitado grep
? Obrigado!
egrep
usa regex estendido, onde |
é entendido como lógica OR. grep
o padrão é o regex básico, onde \|
está OR #
grep
de manual, egrep
está obsoleto e deve ser substituído por grep -E
. Tomei a liberdade de editar a resposta de acordo.
Você pode canalizar a saída do primeiro comando grep para outro comando grep e isso corresponderia aos dois padrões. Então, você pode fazer algo como:
grep <first_pattern> <file_name> | grep <second_pattern>
ou,
cat <file_name> | grep <first_pattern> | grep <second_pattern>
Vamos adicionar alguns conteúdos ao nosso arquivo:
$ echo "This line contains lemon." > test_grep.txt
$ echo "This line contains rice." >> test_grep.txt
$ echo "This line contains both lemon and rice." >> test_grep.txt
$ echo "This line doesn't contain any of them." >> test_grep.txt
$ echo "This line also contains both rice and lemon." >> test_grep.txt
O que o arquivo contém:
$ cat test_grep.txt
This line contains lemon.
This line contains rice.
This line contains both lemon and rice.
This line doesn't contain any of them.
This line also contains both rice and lemon.
Agora, vamos cumprimentar o que queremos:
$ grep rice test_grep.txt | grep lemon
This line contains both lemon and rice.
This line also contains both rice and lemon.
Nós só obtemos as linhas onde ambos os padrões correspondem. Você pode estender isso e canalizar a saída para outro comando grep para outras correspondências "AND".
grep com a opção -P
(Perl-Compatibility) e regex lookahead positivo(?=(regex))
:
grep -P '(?=.*?lemon)(?=.*?rice)' infile
ou você pode usar abaixo:
grep -P '(?=.*?rice)(?=.*?lemon)' infile
.*?
meio que corresponde a qualquer caractere .
que ocorra zero ou mais vezes *
enquanto opcional, seguido de um padrão ( rice
ou lemon
). O ?
faz tudo opcional antes (meio zero ou um tempo de tudo combinado .*
)(?=pattern)
: Lookahead positivo: o construto lookahead positivo é um par de parênteses, com o parêntese de abertura seguido de um ponto de interrogação e um sinal de igual.
Portanto, isso retornará todas as linhas com contém ambos lemon
e rice
em ordem aleatória. Além disso, isso evitará o uso de |
s e o dobro de grep
s.
Links externos:
Tópicos avançados de Grep Lookahead positivo - GREP para designers
Se admitirmos que grep
é aceitável fornecer uma resposta que não seja baseada, como a resposta acima awk
, eu proporia uma perl
linha simples como:
$ perl -ne 'print if /lemon/ and /rice/' my_text_file
A pesquisa pode estar ignorando o caso com algumas / todas as palavras como /lemon/i and /rice/i
. Na maioria das máquinas Unix / Linux, o perl é instalado e o awk de qualquer maneira.
Aqui está um script para automatizar a solução de tubulação grep:
#!/bin/bash
# Use filename if provided as environment variable, or "foo" as default
filename=${filename-foo}
grepand () {
# disable word splitting and globbing
IFS=
set -f
if [[ -n $1 ]]
then
grep -i "$1" ${filename} | filename="" grepand "${@:2}"
else
# If there are no arguments, assume last command in pipe and print everything
cat
fi
}
grepand "$@"
eval
ing-lo, o que quebra facilmente