Estoy usando Solaris 10 y, por lo tanto, las opciones grep que involucran -f no funcionan.
Tengo dos archivos separados por tuberías:
archivo1:
abc|123|BNY|apple|
cab|234|cyx|orange|
def|kumar|pki|bird|
archivo 2:
abc|123|
kumar|pki|
cab|234
Me gustaría comparar las dos primeras columnas del archivo2 con el archivo1 (buscar en todo el contenido del archivo1 en las primeras dos columnas) si coinciden con imprimir la línea coincidente del archivo1. Luego busque la segunda línea del archivo 2 y así sucesivamente.
Rendimiento esperado:
abc|123|BNY|apple|
cab|234|cyx|orange|
Los archivos que tengo son enormes, contienen aproximadamente 400,000 líneas, por lo que me gustaría acelerar la ejecución.
shell-script
text-processing
perl
user68365
fuente
fuente
grep
, está debajo/usr/sfw/bin/ggrep
. stackoverflow.com/questions/15259882/…Respuestas:
Para esto fue diseñado awk:
Explicación
-F'|'
: establece el separador de campo en|
.NR==FNR
: NR es el número de línea de entrada actual y FNR el número de línea del archivo actual. Los dos serán iguales solo mientras se lee el primer archivo.c[$1$2]++; next
: si este es el primer archivo, guarde los dos primeros campos en lac
matriz. Luego, salte a la siguiente línea para que esto solo se aplique en el primer archivo.c[$1$2]>0
: el bloque else solo se ejecutará si este es el segundo archivo, por lo que verificamos si los campos 1 y 2 de este archivo ya se han visto (c[$1$2]>0
) y si lo han sido, imprimimos la línea. Enawk
, la acción predeterminada es imprimir la línea, por lo que sic[$1$2]>0
es verdadera, la línea se imprimirá.Alternativamente, ya que etiquetaste con Perl:
Explicación
Se abrirá la primera línea
file2
, lea todo hasta el segundo|
(.+?\|[^|]+
) y guárdelo ($&
es el resultado del último operador del partido) en el%k
hash.La segunda línea procesa el archivo1, usa la misma expresión regular para extraer las dos primeras columnas e imprimir la línea si esas columnas están definidas en el
%k
hash.Ambos enfoques anteriores necesitarán mantener las 2 primeras columnas del archivo2 en la memoria. Eso no debería ser un problema si solo tiene unos cientos de miles de líneas, pero si lo es, podría hacer algo como
Pero eso será más lento.
fuente
file2
en la memoria?awk -F'|' 'NR==FNR{c[$1$2]++;next};c[$1$2] > 0'
es una versión más corta.file2
Tiene filas duplicadas?Yo creo que
es lo que estás buscando Debería ser eficiente, pero no estoy seguro de que sea tan preciso como quieras. Si
abc|123
(por ejemplo) se encuentra en una líneafile1
en diferentes columnas, esa línea también se imprimirá. Si puede garantizar que esto nunca sucederá, la línea anterior debería funcionar.fuente
Si desea pensar el problema en SQL de la misma manera, entonces definitivamente debería probar una herramienta llamada ' q ':
Es más claro y fácil de entender si está familiarizado con la consulta SQL.
fuente
fuente