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+CD
sem nonAB
e 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 -v
da 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:
Linhas contendo
foo
mais linhas contendobar
(foo OR bar
):grep -e foo -e bar
Linhas contendo
foo
ebar
na mesma linha (foo AND bar
):grep foo | grep bar
Linhas que não contêm
baz
(NOT baz
):grep -v baz
Com esses tijolos você pode construir sua lógica. O problema -v
nã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 bar
com umsolteiro(estendido) grep
:
Novamente linhas contendo
foo
ebar
na 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+CD
semnonAB
enonCD
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+CD
que 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 foobar
no arquivo test.txt
e exibir todas as ocorrências enquanto,
grep "foo" -v "bar" test.txt
irá procurar por linhas que contenham word, foo
mas não bar
. Conseguimos isso por causa-v
switch 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-c
trocar :
-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+CD
ignorar nonAB
e nonCD
contar URLs:
grep "AB+CD" test | grep -cve "non"
onde -v "non"
simplesmente ignorará ambos nonAB
e nonCD
como ambos contêm non
. E -c
dará 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 OR
e significa um de nonAB
ounonCD
exatopalavra especificada por-e
trocar.
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.