Combine todos os padrões do arquivo de uma só vez [duplicado]

1

Eu tenho dois arquivos: args e text . Por exemplo:

args: [contém argumentos de um script]

life
happy
horse

texto:

The horse has a happy life.
Life is fun.
Kids are happy.

Eu preciso de um comando que imprima as linhas de text que contêm todos os padrões de args . Neste caso: The horse has a happy life.

    
por mike-m1342 22.12.2016 / 14:01

4 respostas

1

Você pode usar agrep para aplicar a operação AND . Infelizmente, não é possível aplicar AND a uma lista de padrões em um arquivo, portanto, é necessário expandir isso para um argumento de comando primeiro.

patterns=$(sed 's/;/\;/' <args | tr '\n' ';' | sed 's/;$//')
agrep "$patterns" text

O munging para gerar a lista de padrões une-os com ponto e vírgula. No entanto, não devemos ter um ponto-e-vírgula no final da lista, então isso é removido, e qualquer padrão que já contenha um ponto-e-vírgula deve ter esse caractere escapado, por isso não é tratado como um operador AND . Use echo "$patterns" para ver como o arquivo args é convertido.

    
por 22.12.2016 / 14:27
1

git grep

Aqui está a sintaxe usando git grep combinando vários padrões usando expressões booleanas:

git grep -e "life" --and -e "happy" --and -e "horse"

O comando acima imprimirá linhas correspondentes a todos os padrões de uma só vez.

Se os arquivos não estiverem sob controle de versão, adicione --no-index param.

Search files in the current directory that is not managed by Git.

Verifique man git-grep para ajuda.

grep

Normalmente, o parâmetro grep com -f imprime linhas com pelo menos um padrão, por exemplo,

grep -f args.txt file.txt

No seu caso, não funcionará.

Para imprimir linhas que correspondam a todos os padrões ao mesmo tempo, você pode tentar este comando:

while read n text; do [ $n -eq $(wc -l < args.txt) ] && echo $text; done < <(while read patt; do grep "$patt" text.txt; done < args.txt | sort | uniq -c)

Explicação:

  1. O loop while interno imprimirá todas as linhas que corresponderem a pelo menos um padrão em text.txt usando a lista de padrões do arquivo args.txt .
  2. Em seguida, essa lista é classificada ( sort ) e contada para o número de ocorrências ( uniq -c ).
  3. O loop externo while imprimirá apenas as linhas que tiverem o mesmo número de ocorrências que o número de padrões em args.txt (que é 3).

Outra abordagem seria remover todas as linhas que não correspondam a pelo menos um padrão.

Aqui está a solução usando o editor Ex / Vim para alterar o arquivo no local:

while read patt; do ex +"v/$patt/d" -scwq text.txt; done < args.txt

Nota: Isso removerá as linhas desnecessárias do próprio arquivo.

Aqui está uma versão mais curta que imprimirá o resultado somente na tela:

ex $(xargs -I% printf "+v/%/d " < args.txt) +%p -scq! text.txt

Altere +%p -scq! para -scwq para salvá-lo no local no arquivo.

E aqui está a solução, definindo um alias de shell:

alias grep-all="</dev/stdin $(xargs printf '|grep "%s"' < args.txt)"

Uso da amostra:

grep-all file.txt

Relacionados:

por 22.12.2016 / 14:55
0

Use awk .

~$ cat textlist.txt | awk '/life/ && /happy/ && /horse/ { print; }'
The horse has a happy life

textlist.txt sendo a lista de frases que você deu.

    
por 22.12.2016 / 14:06
0

Talvez essa não seja a maneira mais eficiente de fazer isso, mas parece funcionar:

# for a in $(cat args); do regex="$regex | grep '$a'"; done
# eval cat text "$regex"
The horse has a happy life.
    
por 22.12.2016 / 14:30

Tags