linux - ocultos - grep una lista grande contra un archivo grande
como encontrar la ubicacion de un archivo en linux (3)
Actualmente estoy tratando de grep
una gran lista de identificadores (~ 5000) en contra de un archivo csv aún mayor (3.000.000 líneas).
Quiero todas las líneas de csv, que contienen una identificación del archivo de id.
Mi enfoque ingenuo fue:
cat the_ids.txt | while read line
do
cat huge.csv | grep $line >> output_file
done
¡Pero esto toma para siempre!
¿Hay enfoques más eficientes para este problema?
Tratar
grep -f the_ids.txt huge.csv
Además, dado que sus patrones parecen ser cadenas fijas, el suministro de la opción -F
podría acelerar grep
.
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
Use grep -f
para esto:
grep -f the_ids.txt huge.csv > output_file
Del man grep
:
-f FILE, --file = ARCHIVO
Obtenga patrones de FILE, uno por línea. El archivo vacío contiene cero patrones, y por lo tanto no coincide con nada. (-f es especificado por POSIX)
Si proporciona alguna entrada de muestra, tal vez podamos mejorar un poco más la condición grep
.
Prueba
$ cat ids
11
23
55
$ cat huge.csv
hello this is 11 but
nothing else here
and here 23
bye
$ grep -f ids huge.csv
hello this is 11 but
and here 23
grep -f
vuelve ingobernable con archivos más grandes. Incluso al usar grep -f
, debemos tener en cuenta algunas cosas:
- use la opción
-x
si es necesario hacer coincidir toda la línea en el segundo archivo - use
-F
si el primer archivo tiene cadenas, no patrones - use
-w
para evitar coincidencias parciales sin usar la opción-x
Esta publicación tiene una gran discusión sobre este tema ( grep -f
en archivos grandes):
Y este post habla sobre grep -vf
:
En resumen, la mejor manera de manejar grep -f
en archivos grandes es:
Coincidencia de toda la línea:
awk ''FNR==NR {hash[$0]; next} $0 in hash'' filter.txt data.txt > matching.txt
Coincidencia de un campo particular en el segundo archivo (usando el delimitador '','' y el campo 2 en este ejemplo):
awk -F, ''FNR==NR {hash[$1]; next} $2 in hash'' filter.txt data.txt > matching.txt
y para grep -vf
:
Coincidencia de toda la línea:
awk ''FNR==NR {hash[$0]; next} !($0 in hash)'' filter.txt data.txt > not_matching.txt
Coincidencia de un campo particular en el segundo archivo (usando el delimitador '','' y el campo 2 en este ejemplo):
awk -F, ''FNR==NR {hash[$0]; next} !($2 in hash)'' filter.txt data.txt > not_matching.txt