Buscar valor de columna duplicado en CSV

Buscar valor de columna duplicado en CSV

Estoy tratando de encontrar identificadores duplicados en un archivo csv grande, solo hay un registro por línea, pero la condición para encontrar un duplicado será la primera columna.<id>,<value>,<date>

ejemplo.csv

11111111,high,6/3/2019
22222222,high,6/3/2019
33333333,high,6/3/2019
11111111,low,5/3/2019
11111111,medium,7/3/2019

Salida deseada:

11111111,high,6/3/2019
11111111,low,5/3/2019
11111111,medium,7/3/2019

No se requiere ningún pedido para la salida.

Respuesta1

Usando AWK:

awk -F, 'data[$1] && !output[$1] { print data[$1]; output[$1] = 1 }; output[$1]; { data[$1] = $0 }'

Esto analiza cada línea y se comporta de la siguiente manera:

  • si ya hemos visto el valor en la primera columna, tenga en cuenta que debemos generar cualquier línea que coincida con ese valor y generar la línea memorizada;
  • generar la línea actual si su primera columna coincide con la que queremos generar;
  • almacenar la línea actual escrita en la primera columna.

Respuesta2

Si todos sus ID tienen la misma longitud (8 caracteres en su ejemplo), puede hacer todo usando sortGNU uniq:

$ sort file | uniq -Dw 8
11111111,high,6/3/2019
11111111,low,5/3/2019
11111111,medium,7/3/2019

Si no tienen la misma longitud, aún puedes usar este enfoque, pero se vuelve un poco más complicado:

$ tr ',' ' ' < file | sort  | rev | uniq -f2 -D | rev | tr ' ' ','
11111111,high,6/3/2019
11111111,low,5/3/2019
11111111,medium,7/3/2019

Respuesta3

awk -F, '$1 in m { print m[$1]$0; m[$1]=""; next } 
                 { m[$1]=$0 "\n" }' ex

Respuesta4

Esto se puede hacer utilizando GNU sedsus construcciones de expresiones regulares extendidas. Primero cargamos el archivo en el espacio de patrón y luego eliminamos cualquier línea que no se repita desde el comienzo del espacio de patrón. Además, \n\nse coloca una bandera, , al final del espacio del patrón, donde colocamos las líneas repetidas. Entonces, una vez que esta bandera aparece hasta el comienzo del espacio del patrón => la operación termina y ahora podemos continuar y eliminar los marcadores del espacio del patrón e imprimir en la salida estándar.

$ sed -Ee '
   $!{
      N;s/^/\n/
      $s/$/\n\n/;D
   }
   /^([^,\n]*),[^\n]*\n(.*\n)?\1,/!D
   s/^([^\n]*)(.*)/\2\1\n/;/^\n\n/!D
   s/^\n\n//;s/\n$//
' inp

Esta es una POSIX-sedversión Y otra forma de abordar el problema en la que no mantenemos el archivo completo en ningún momento ni en el patrón ni en los espacios de retención. Tan pronto como se ve una línea duplicada, se imprime en la salida estándar Y la línea de referencia se marca e imprime, marcada porque no queremos imprimirla la próxima vez que se vea un duplicado.

$ sed -ne '
   H;g;y/\n_/_\n/
   /.*_\([^,_]*\)\(,[^_]*\)\[0]_\(.*_\)\{0,1\}\1,[^_]*$/{
      s//\1\2/;y/_\n/\n_/;p
      g;s/.*\n//p;g;y/\n_/_\n/
      s/\(.*_\([^,_]*\),[^_]*\)\[0]\(_\(.*_\)\{0,1\}\)\2,[^_]*$/\1[1]\3/
      s/_$//;y/_\n/\n_/;bh
   }
   /.*_\([^,_]*\)\(,[^_]*\)\[1]_\(.*_\)\{0,1\}\1,[^_]*$/{
      s/.*_//;y/_\n/\n_/;p
      g;s/\(.*\)\n.*/\1/;bh
   }
   y/_\n/\n_/;s/$/[0]/;:h;h
' inp

Esta es una Perlsolución basada en el problema en el que mantenemos las líneas en un hash de matriz. Tan pronto como vemos una línea repetida, imprimimos la matriz y también la vaciamos, y también imprimimos la línea duplicada.

$ perl -F, -lane '
   push(@{$h{$F[0]}},$_),next if ! exists $h{$F[0]};
   print for splice(@{$h{$F[0]}}),$_;
' inp

Producción:

11111111,high,6/3/2019
11111111,low,5/3/2019
11111111,medium,7/3/2019

información relacionada