Verifique se todos os padrões estão no arquivo

Verifique se todos os padrões estão no arquivo

Digamos que eu tenha um patterns.txte queira verificar se cada um desses padrões está presente em algum arquivo.

Eu poderia fazer algo como:

for pattern in $(cat patterns.txt); do 
  if ! grep -q "$pattern" file.txt; then
    echo "Error: missing pattern $pattern"
  fi
done
echo "All patterns found"

mas isso é ineficiente, pois é necessário verificar novamente file.txtcada padrão (e não é tão simples se, em vez de um arquivo, estivermos procurando padrões em um fluxo proveniente de um canal que pode ser grande, por exemplo).

Existe uma maneira de grep(ou alguma outra ferramenta) verificar setodosos padrões estão presentes?

Responder1

cat file.txt | awk '
    NR == FNR {seen[$0] = 0; next} 
    {for (p in seen) if ($0 ~ p) seen[p]++} 
    END {
        for (p in seen) 
            if (seen[p] == 0) {
                missing++
                print "missing pattern", p
            } 
        if (missing == 0) print "all found"
        exit missing
    }
' patterns.txt -

Substitua o catcomando por qualquer pipeline que produza texto.

Responder2

Isso pode funcionar bem:

sort -u patterns.txt > sorted_patterns.txt # only once
diff -sq <(grep -o -f sorted_patterns.txt file.txt | sort -u) sorted_patterns.txt

Se você tiver strings fixas em vez de padrões, use -F. Isso torna grepmuito mais rápido!

Você poderiatambém usecmpem vez de diff -s. Isso pode ser um pouco mais rápido, mas não será capaz de mostrar o que está faltando.


Saída se nem todos os padrões foram encontrados:

Files /dev/fd/63 and /dev/fd/62 differ

ou se todos os padrões foram encontrados:

Files /dev/fd/63 and /dev/fd/62 are identical

Deixe de fora -qpara sabero queestá desaparecido.

2a3
> missing_word

Responder3

com grepextensão PCRE e também usando poder de printfcomando; você faria algo como:

<infile grep -qzP "(?s)$(printf "(?=.*?%s)" $(<pattern.txt))" &&
 echo 'all matched' ||
 echo 'one or more pattern(s) does not found'

se todos os padrões (emqualquer ordem) encontrado no arquivo de entradano arquivoentão envie uma mensagemall matchedwill vai para a saída; caso contrário, textoone or more pattern(s) does not foundirá ecoar.

isso atuará como padrão como um padrão correspondente, como pat[01]corresponderá a pat0& pat1; para corresponder ao padrão exato, diga pat[01]literalmente alterar printfo modificador de controle do %squal %qescapará dos caracteres especiais.

<infile grep -qzP "(?s)$(printf "(?=.*?%q)" $(<pattern.txt))" &&
 echo 'all matched' ||
 echo 'one or more pattern(s) does not found'

informação relacionada