tagger tag puddletag mp3tag mac kid3 editar easytag linux shell sorting uniq

linux - mp3tag - puddletag



¿Hay alguna manera de ''uniq'' por columna? (8)

Al ordenar el archivo primero con sort , puede aplicar uniq .

Parece ordenar bien el archivo:

$ cat test.csv [email protected],2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 $ sort test.csv [email protected],2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 [email protected],2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 $ sort test.csv | uniq [email protected],2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0 [email protected],2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1

También puedes hacer algo de magia AWK:

$ awk -F, ''{ lines[$1] = $0 } END { for (l in lines) print lines[l] }'' test.csv [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1 [email protected],2009-11-27 00:58:29.646465785,2x3.net,256.255.255.0

Tengo un archivo .csv como este:

[email protected],2009-11-27 01:05:47.893000000,example.net,127.0.0.1 [email protected],2009-11-27 00:58:29.793000000,example.net,255.255.255.0 [email protected],2009-11-27 00:58:29.646465785,example.net,256.255.255.0 ...

Tengo que eliminar los correos electrónicos duplicados (toda la línea) del archivo (es decir, una de las líneas que contiene [email protected] en el ejemplo anterior). ¿Cómo uso uniq solo en el campo 1 (separado por comas)? Según el man , uniq no tiene opciones para columnas.

Intenté algo con sort | uniq sort | uniq pero no funciona


Aquí hay una manera muy ingeniosa.

Primero formatee el contenido de manera que la columna que se va a comparar por singularidad tenga un ancho fijo. Una forma de hacerlo es usar awk printf con un especificador de ancho de campo / columna ("% 15s").

Ahora las opciones -f y -w de uniq se pueden usar para omitir los campos / columnas precedentes y para especificar el ancho de la comparación (ancho de columna (s)).

Aquí hay tres ejemplos.

En el primer ejemplo ...

1) Haga temporalmente que la columna de interés tenga un ancho fijo mayor o igual que el ancho máximo del campo.

2) Utilice la opción -f uniq para omitir las columnas anteriores, y use la opción -w uniq para limitar el ancho al tmp_fixed_width.

3) Elimine los espacios finales de la columna para "restaurar" su ancho (suponiendo que no haya espacios finales de antemano).

printf "%s" "$str" / | awk ''{ tmp_fixed_width=15; uniq_col=8; w=tmp_fixed_width-length($uniq_col); for (i=0;i<w;i++) { $uniq_col=$uniq_col" "}; printf "%s/n", $0 }'' / | uniq -f 7 -w 15 / | awk ''{ uniq_col=8; gsub(/ */, "", $uniq_col); printf "%s/n", $0 }''

En el segundo ejemplo ...

Cree una nueva columna uniq 1. Luego, quítela una vez que se haya aplicado el filtro uniq.

printf "%s" "$str" / | awk ''{ uniq_col_1=4; printf "%15s %s/n", uniq_col_1, $0 }'' / | uniq -f 0 -w 15 / | awk ''{ $1=""; gsub(/^ */, "", $0); printf "%s/n", $0 }''

El tercer ejemplo es el mismo que el segundo, pero para múltiples columnas.

printf "%s" "$str" / | awk ''{ uniq_col_1=4; uniq_col_2=8; printf "%5s %15s %s/n", uniq_col_1, uniq_col_2, $0 }'' / | uniq -f 0 -w 5 / | uniq -f 1 -w 15 / | awk ''{ $1=$2=""; gsub(/^ */, "", $0); printf "%s/n", $0 }''


Bueno, más simple que aislar la columna con awk, si necesita eliminar todo con un cierto valor para un archivo dado, ¿por qué no simplemente grep -v:

por ejemplo, para eliminar todo con el valor "col2" en la segunda línea del lugar: col1, col2, col3, col4

grep -v '',col2,'' file > file_minus_offending_lines

Si esto no es lo suficientemente bueno, debido a que es posible que algunas líneas se eliminen incorrectamente al tener el valor coincidente en una columna diferente, puede hacer algo como esto:

awk para aislar la columna ofensiva: por ej.

awk -F, ''{print $2 "|" $line}''

el -F establece el campo delimitado a ",", $ 2 significa la columna 2, seguido de un delimitador personalizado y luego la línea completa. A continuación, puede filtrar eliminando las líneas que comienzan con el valor ofensivo:

awk -F, ''{print $2 "|" $line}'' | grep -v ^BAD_VALUE

y luego quita las cosas antes del delimitador:

awk -F, ''{print $2 "|" $line}'' | grep -v ^BAD_VALUE | sed ''s/.*|//g''

(Nota: el comando sed es descuidado porque no incluye valores de escape. También el patrón de sed debería ser algo así como "[^ |] +" (es decir, cualquier cosa que no sea el delimitador). Pero espero que esto sea lo suficientemente claro.


Para considerar columna múltiple.

Clasifique y proporcione una lista única basada en la columna 1 y la columna 3:

sort -u -t : -k 1,1 -k 3,3 test.txt

  • -t : dos puntos es separador
  • -k 1,1 -k 3,3 según la columna 1 y la columna 3

Si desea conservar el último de los duplicados, puede usar

tac a.csv | sort -u -t, -r -k1,1 |tac

Cual era mi requisito

aquí

tac revertirá el archivo línea por línea


o si quieres usar uniq:

<mycvs.cvs tr -s '','' '' '' | awk ''{print $3" "$2" "$1}'' | uniq -c -f2

da:

1 01:05:47.893000000 2009-11-27 [email protected] 2 00:58:29.793000000 2009-11-27 [email protected] 1


awk -F"," ''!_[$1]++'' file

  • -F establece el separador de campo.
  • $1 es el primer campo.
  • _[val] busca val en el hash _ (una variable regular).
  • ++ incremente y devuelva el valor anterior.
  • ! devuelve lógica no.
  • hay una impresión implícita al final.

sort -u -t, -k1,1 file

  • -u para único
  • -t, entonces la coma es el delimitador
  • -k1,1 para el campo clave 1

Resultado de la prueba:

[email protected],2009-11-27 00:58:29.793000000,xx3.net,255.255.255.0 [email protected],2009-11-27 01:05:47.893000000,xx2.net,127.0.0.1