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 grep
verificar (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 cat
comando 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 grep
mucho más rápido!
Tú podríastambién usocmp
en 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 grep
una extensión PCRE y también usando el poder del printf
comando; 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 matched
la voluntad va a la salida; de lo contrario textoone or more pattern(s) does not found
hará 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 printf
el modificador de control desde %s
el %q
cual 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'