"Ungrep" - quais padrões não correspondem


13

Estou procurando um comando ou script para fazer o seguinte - dado:

file1.txt:

abcd
efgh 
ijkl
mnop

file2.txt:

123abcd123
123efgh123
123mnop123

Eu quero um comando que faça algo parecido com isto:

ungrep file1.txt file2.txt

e retorna o seguinte:

ijkl

Em outras palavras, ele está fornecendo as linhas no arquivo1.txt que não retornarão nenhum resultado em um grep do arquivo2.txt. Eu sei que posso fazer isso iterando através de file1.txt, grepping file2.txt para cada linha e armazenando o resultado e emitindo todas as linhas em que o resultado está vazio, mas eu esperava uma maneira mais eficiente de fazer isso.

Respostas:


18

Com o GNU, grepo seguinte deve funcionar. Usando a -fopção, passe file1.txtcomo um "arquivo padrão" - mas também passe pela segunda vez como um arquivo de dados. Use -opara relatar apenas as partes correspondentes. Por fim, extrai as palavras que correspondem apenas uma vez - elas correspondem às linhas das file1.txtquais não há correspondência file2.txt.

grep -h -o -f  file1.txt file2.txt file1.txt | sort | uniq -u
ijkl

Descrição muito boa. Obrigado e +1.
unxnut

4
Você pode obter o mesmo efeito sem o truque do grep:, sort file1.txt <(grep -of file1.txt file2.txt) | uniq -umas, como sua solução, isso só funciona quando o arquivo padrão não contém metacaracteres de expressão regular.
rici

@rici, que é um ponto muito bom
Iruvar

2
Melhoria:grep -oFf file1.txt file2.txt | sort file1.txt - | uniq -u
Stéphane Chazelas

10

Você poderia fazê-lo com awk:

awk '
  NR == FNR {w[$0]; next}
  {for (i in w) if (index($0,i)) delete w[i]}
  END {for (i in w) print i}' file1.txt file2.txt

Ao usar index, procuramos substrings em vez de corresponder expressões regulares.

Como excluímos a palavra da matriz assim que encontramos uma correspondência, evitamos pesquisas desnecessárias.


1
Eu só aceitaria este. Ele não invoca nenhuma classificação O (n log n) e não falha estranhamente quando os padrões contêm metacaracteres de expressões regulares e pode ser estendido para suportar expressões regulares.
Kaz

Não acredito que a simples avaliação w[$0]tenha o efeito colateral de adicionar a chave à matriz.
Kaz

1
@ Kaz, sim, isso pode ser confuso, e você encontra muitos scripts que não alocam intencionalmente elementos da matriz sem querer, fazendo isso em if (a[$1])vez de, if ($1 in a)por exemplo. É o caso de todos, awkincluindo o original awke nawk, mas olhando para o padrão de ontem, não consegui encontrá-lo especificado.
Stéphane Chazelas

1
@Kaz Aqui está a citação do POSIX: "O aplicativo deve garantir que um índice multidimensional usado com o operador in esteja entre parênteses. O operador in , que testa a existência de um elemento específico da matriz, não deve causar a existência desse elemento. Qualquer outra referência a um elemento inexistente da matriz deve criá-lo automaticamente. " Pode ser encontrado rolando um parágrafo ou dois aqui em cima .
Jk013

1
Contanto que file1não seja grande (por algum valor enorme), eu preferiria essa solução, pois não requer nenhuma classificação file2e seria muito mais eficiente.
Jk013
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.