Eliminar líneas duplicadas con un giro

De acuerdo, quiero eliminar líneas duplicadas, pero es un poco más complicado que eso …

Tengo un file llamado users.txt, el ejemplo del file es:

users:email@email.com users1:email@email.com 

Ahora, debido a un error en mi sistema, las personas pudieron registrarse con el mismo correo electrónico que otra persona, por lo que quiero eliminar si las líneas tienen el mismo correo electrónico más de una vez, ejemplo de problema:

  user:display:email@email.com user2:email@email.com user3:email@email.com user4:email@email.com 

Observe cómo el usuario, usuario2, usuario3, usuario4 todos tienen el mismo correo electrónico … bueno, quiero eliminar usuario2, usuario3, usuario4 pero mantener al usuario … o viceversa (el primero que se recoja por request) elimine cualquier otra línea que contenga el mismo correo electrónico..

Así que si

  email@email.com is in 20 lines remove 19 spam@spam.com is in 555 lines remove 554 and so fourth.. 

Solutions Collecting From Web of "Eliminar líneas duplicadas con un giro"

Esto requiere Awk. Como el campo que desea verificar es el primer campo de cada línea, simplemente haga reference a $1 .

 awk -F: '! ($1 in seen) {print; seen[$1]}' users.txt 

Puedes "golf" esto para networkingucirlo considerablemente:

 awk -F: '!a[$1]++' users.txt 

La forma más larga es más o less autoexplicativa; construyes una matriz asociativa usando cada dirección de correo electrónico como un índice, sin molestarte en asignar un valor. Luego puede verificar si la dirección de correo electrónico se ha "visto" anteriormente (es decir, si la matriz asociativa ya tiene una dirección de correo electrónico particular como índice) e imprimir toda la línea si no es así.

La forma más corta en realidad está haciendo más o less lo mismo, pero requiere más explicación para el código más corto.

El operador postfix ++ actúa sobre una variable después de que se evalúa la expresión, por lo que volveremos sobre eso más adelante.

En Awk, 0 significa falso y no cero significa verdadero. ! es para la negación y revierte el valor de verdad.

Apareciendo como lo hace fuera de los corchetes, la expresión se interpreta como una expresión booleana, con una acción asociada (entre llaves) que se realizará si la expresión es verdadera. Como no se indica explícitamente ninguna acción, se usa la acción pnetworkingeterminada (implícita) de imprimir toda la línea, si la expresión se evalúa como verdadera (distinta de cero).

Esencialmente, esto recupera el valor en la matriz asociativa a que apunta a la dirección de correo electrónico (primer campo) como su índice, o crea ese valor inicializado como 0 si no está presente, interpreta un 0 como falso o distinto de cero como verdadero , invierte este valor de verdad e imprime toda la línea si el resultado es "verdadero", y luego incrementa el valor almacenado en la matriz asociativa en ese punto.

Un idioma bastante común en Awk, en realidad, pero no te culpo por usar la versión más larga y explícita. 🙂

  1. Use el datamash GNU para agrupar las inputs en el segundo campo y conserve solo la primera línea de cada agrupación:

     datamash -t':' -g 2 rmdup 2 < users.txt 
  2. Como comentario de notas de don_crissti , sort puede hacerlo, pero mientras devuelve los resultados deseados, también puede reorderar el resultado:

     sort -t':' -k 2,2 -u users.txt 

El código anterior asume que users.txt está orderado por el segundo campo, luego el primer campo.