Encuentre coincidencias para la quinta columna en archivos delimitadores de tuberías

Encuentre coincidencias para la quinta columna en archivos delimitadores de tuberías
File 1:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
File 2:
Connect|20130320000023|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Necesito encontrar registros coincidentes tanto en el Archivo 1 como en el Archivo 2 en la columna 5. Entonces, de lo anterior necesito regresar en el resultado:

Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Muchas gracias,

Respuesta1

Método n.º 1: grep y awk

Puedes usar este fragmento para hacerlo:

$ grep -f <(awk -F '|' '{print $5}' file1)  file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Detalles

El bit que utiliza awkanaliza el primer archivo y file1extrae la quinta columna. Estos valores luego se usan como una lista grep, que imprimirá cualquier línea en el segundo archivo que contenga una coincidencia.

Advertencias con este método

Este método coincidirá con cualquier aparición de la quinta columna file1de file2.

Método #2: Simplemente extraño

Otro enfoque que se ha utilizado en el sitio en el pasado es utilizar awkla instalación FNR. Aquí es donde awkse iterará sobre 2 archivos, recorriendo el segundo archivo línea por línea, para cada línea del primero.

Un enfoque como este sería suficiente. Coloque lo siguiente en un archivo cmds.awk:

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 == f1[$5]) print $0; }

Luego puede ejecutar esto de la siguiente manera:

$ awk -F '|' -f cmds.awk file1 file2

NOTA:Podrías haber usado este awkpatrón en su lugar:

FNR == NR {
f1[$5] = $5
next
}

{ if ($5 in f1) print $0; }

Ejemplo

$ awk -F '|' -f s.awk file1 file2
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|

Advertencias con este método

Este enfoque solo puede manejar una única instancia de cada dirección de correo electrónico de file1. Entonces, si hay 2 líneas que tienen el mismo valor para la quinta columna, no se podrán distinguir entre ellas. Sin embargo, esto parece aceptable dados sus requisitos en el OP.

Unirse y ordenar

También puedes hacer esto usando joiny sort.

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'

Esto utilizará el separador |y unirá los archivos ordenados en la quinta columna. Este enfoque imprime las coincidencias de ambos file1y file2, por lo que utilizamos sedpara cortar la segunda coincidencia del final.

Ejemplo

$ join -t '|' -j 5  <(sort -k5,5 file2) <(sort -k5,5 file1) | sed 's/||.*//'
[email protected]|Connect|20130320000025|UTC|PPP|[email protected]|0BCBE578

Respuesta2

Haría todo en Perl:

$ perl -F'\|' -ane '$k{$F[4]}++; print if $k{$F[4]}>1' file1 file2  
Connect|20130320000025|UTC|PPP|[email protected]|[email protected]|0BCBE578|
  • -aactiva la división automática de campos en la matriz @F.
  • -F'\|'establece el delimitador de campo para -aen |.
  • Para cada línea procesada, guarde el quinto campo (los índices de matriz comienzan en 0Perl) como una clave hash ( $k{$F[4]}++e incremente su valor en uno. La segunda vez que se vea un campo, ese valor será 2.
  • El script procesará cada línea de ambos archivos ( file1antes file2) e imprimirá la línea si el quinto campo se ha visto antes, es decir, si $k{$F[4]}es mayor que uno.

Esto supone que no se repite ninguna quinta columna dentro delmismoarchivo. Si este no es el caso y algunas columnas pueden estar duplicadas en el mismo archivo, utilice esto en su lugar:

perl -e 'open(A,"$ARGV[0]"); while(<A>){@F=split(/\|/);$k{$F[4]}++;}
         open(B,"$ARGV[1]"); while(<B>){@F=split(/\|/); print if $k{$F[4]} 
         }' file1 file2 

Respuesta3

Si los tamaños de los archivos son comparables, la solución óptima essortambos archivos por la columna que le interesa y luegojoinellos por esa columna. Si los tamaños de los archivos son Ny Mentonces el tiempo de ejecución asintótico es O(N*log(N)+M*log(M)).

Si uno de los archivos es mucho más pequeño que el otro, entonces la O(N*M)solución en las otras respuestas es mejor.

información relacionada