Compruebe si todos los patrones están en el archivo

Compruebe si todos los patrones están en el archivo

decir que tengo unpatterns.txt y quiero comprobar si cada uno de esos patrones está presente en algún archivo.

Podría hacer 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"

pero esto es ineficiente ya que tiene que volver a escanearfile.txt para cada patrón (y no es tan simple si en lugar de un archivo buscamos patrones en una secuencia proveniente de una tubería que puede ser grande, por ejemplo).

¿Hay alguna manera de grepverificar (o alguna otra herramienta) sitodo¿Los patrones están presentes?

Respuesta1

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 -

Reemplace el catcomando con cualquier canalización que produzca texto.

Respuesta2

Esto podría funcionar bien:

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

Si tiene cadenas fijas en lugar de patrones, use -F. ¡Esto hace grepmucho más rápido!

Tú podríastambién usocmpen lugar de diff -s. Quizás sea un poco más rápido, pero no podrá mostrar lo que falta.


Salida si no se han encontrado todos los patrones:

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

o si se han encontrado todos los patrones:

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

Dejar-q para saberquéEstá perdido.

2a3
> missing_word

Respuesta3

con grepuna extensión PCRE y también usando el poder del printfcomando; harías algo como:

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

si todos los patrones (encualquier orden) encontrado en el archivo de entradaen archivoluego envía un mensaje de textoall matchedla voluntad va a la salida; de lo contrario textoone or more pattern(s) does not foundhará eco.

esto actuará como un patrón coincidente, al igual que pat[01]coincidirá con pat0& pat1; para que coincida con el patrón exacto, diga pat[01]literalmente cambiar printfel modificador de control desde %sel %qcual se escaparán los caracteres especiales.

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

información relacionada