Tengo un archivo .csv como este:
stack2@example.com,2009-11-27 01:05:47.893000000,example.net,127.0.0.1
overflow@example.com,2009-11-27 00:58:29.793000000,example.net,255.255.255.0
overflow@example.com,2009-11-27 00:58:29.646465785,example.net,256.255.255.0
...
Tengo que eliminar correos electrónicos duplicados (toda la línea) del archivo (es decir, una de las líneas que contiene [email protected]
el ejemplo anterior). ¿Cómo se usa uniq
solo en el campo 1 (separado por comas)? Según man
, uniq
no tiene opciones para columnas.
Intenté algo con sort | uniq
pero no funciona.
man sort
). Representa la posición de inicio y parada.sort
dice la página de manual: "-u
,--unique
con-c
, compruebe el orden estricto; sin-c
, solo muestra el primero de una ejecución igual ". Por lo tanto, es "la primera aparición del duplicado antes de ordenar".-F
establece el separador de campo.$1
Es el primer campo._[val]
buscaval
en el hash_
(una variable regular).++
incrementar y devolver el valor anterior.!
devuelve lógico no.fuente
awk -F',' '{ x[$1]=$0 } END { for (i in x) print x[i] }' file
!_[$1][$2]++
se puede usar para ordenar por los dos primeros campos. Sinawk
embargo, mi -fu no es lo suficientemente fuerte como para ser único en una variedad de campos. :(Para considerar múltiples columnas.
Ordenar y dar una lista única basada en la columna 1 y la columna 3:
-t :
el colon es separador-k 1,1 -k 3,3
basado en la columna 1 y la columna 3fuente
o si quieres usar uniq:
<mycvs.cvs tr -s ',' ' ' | awk '{print $3" "$2" "$1}' | uniq -c -f2
da:
fuente
cat
! En lugar de conectarlo a tr, simplemente deje que tr lea el archivo usando<
. La canalizacióncat
es una complicación innecesaria común utilizada por los novatos. Para grandes cantidades de datos hay un efecto de rendimiento.rev
.Si desea conservar el último de los duplicados, puede usar
Cual era mi requerimiento
aquí
tac
revertirá el archivo línea por líneafuente
Aquí hay una manera muy ingeniosa.
Primero formatee el contenido de modo que la columna que se va a comparar para la unicidad sea de ancho fijo. Una forma de hacerlo es utilizar awk printf con un especificador de ancho de campo / columna ("% 15s").
Ahora las opciones -f y -w de uniq se pueden usar para omitir campos / columnas anteriores y para especificar el ancho de comparación (ancho de columna (s)).
Aquí hay tres ejemplos.
En el primer ejemplo ...
1) Haga que la columna de interés tenga un ancho fijo mayor o igual que el ancho máximo del campo.
2) Use la opción -f uniq para omitir las columnas anteriores, y use la opción -w uniq para limitar el ancho a tmp_fixed_width.
3) Elimine los espacios finales de la columna para "restaurar" su ancho (suponiendo que no haya espacios finales de antemano).
En el segundo ejemplo ...
Cree una nueva columna uniq 1. Luego quítela después de que se haya aplicado el filtro uniq.
El tercer ejemplo es el mismo que el segundo, pero para varias columnas.
fuente
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 hacer grep -v:
por ejemplo, para eliminar todo con el valor "col2" en la línea del segundo lugar: col1, col2, col3, col4
Si esto no es lo suficientemente bueno, debido a que algunas líneas pueden ser eliminadas de manera incorrecta al tener el valor correspondiente en una columna diferente, puede hacer algo como esto:
awk para aislar la columna infractora: por ejemplo
-F establece el campo delimitado en ",", $ 2 significa columna 2, seguido de un delimitador personalizado y luego toda la línea. Luego puede filtrar eliminando líneas que comienzan con el valor ofensivo:
y luego quitar las cosas antes del delimitador:
(nota: el comando sed es descuidado porque no incluye valores de escape. Además, el patrón sed debería ser algo así como "[^ |] +" (es decir, cualquier cosa que no sea el delimitador). Pero espero que esto sea lo suficientemente claro.
fuente
Al ordenar el archivo
sort
primero, puede aplicaruniq
.Parece ordenar el archivo muy bien:
También podrías hacer algo de magia AWK:
fuente
sort
, entoncesuniq
,sort
debe hacerse antes de hacerlo, de louniq
contrario no funciona (pero puede omitir el segundo comando y simplemente usarlosort -u
). Desdeuniq(1)
: "Filtrar líneas coincidentes adyacentes desde INPUT (o entrada estándar), escribiendo en OUTPUT (o salida estándar)".