linux - repetidas - eliminar lineas duplicadas txt
Cómo eliminar palabras duplicadas de un archivo de texto sin formato mediante el comando linux (10)
Tengo un archivo de texto plano con palabras, que están separadas por comas, por ejemplo:
word1, word2, word3, word2, word4, word5, word 3, word6, word7, word3
Quiero borrar los duplicados y convertirme en:
word1, word2, word3, word4, word5, word6, word7
¿Algunas ideas? Creo que, egrep puede ayudarme, pero no estoy seguro, cómo usarlo exactamente ...
Aquí hay un script awk que dejará cada línea intacta, solo eliminando las palabras duplicadas:
BEGIN {
FS=", "
}
{
for (i=1; i <= NF; i++)
used[$i] = 1
for (x in used)
printf "%s, ",x
printf "/n"
split("", used)
}
Crear una lista única es bastante fácil gracias a uniq
, aunque la mayoría de los comandos de Unix son como una entrada por línea en lugar de una lista separada por comas, por lo que debemos comenzar convirtiéndolo a eso:
$ sed ''s/, //n/g'' filename | sort | uniq
word1
word2
word3
word4
word5
word6
word7
La parte más difícil es poner esto en una línea nuevamente con comas como separadores y no como terminadores. Utilicé un perl one-liner para hacer esto, pero si alguien tiene algo más idiomático, edíteme. :)
$ sed ''s/, //n/g'' filename | sort | uniq | perl -e ''@a = <>; chomp @a; print((join ", ", @a), "/n")''
word1, word2, word3, word4, word5, word6, word7
Creo que querrá reemplazar los espacios con nuevas líneas, use el comando uniq para encontrar líneas únicas y luego reemplace las nuevas líneas con espacios nuevamente.
Encontré este hilo mientras intentaba resolver el mismo problema. Había concatenado varios archivos que contenían contraseñas, así que naturalmente había muchos dobles. Además, muchos personajes no estándar. Realmente no los necesitaba ordenados, pero parecía que iba a ser necesario para uniq.
Lo intenté:
sort /Users/me/Documents/file.txt | uniq -u
sort: string comparison failed: Illegal byte sequence
sort: Set LC_ALL=''C'' to work around the problem.
sort: The strings compared were `t/203tonnement'' and `t/203tonner''
Intentó:
sort -u /Users/me/Documents/file.txt >> /Users/me/Documents/file2.txt
sort: string comparison failed: Illegal byte sequence
sort: Set LC_ALL=''C'' to work around the problem.
sort: The strings compared were `t/203tonnement'' and `t/203tonner''.
E incluso intenté pasarlo a través del gato primero, solo para que pudiera ver si obteníamos una entrada adecuada.
cat /Users/me/Documents/file.txt | sort | uniq -u > /Users/me/Documents/file2.txt
sort: string comparison failed: Illegal byte sequence
sort: Set LC_ALL=''C'' to work around the problem.
sort: The strings compared were `zon/351s'' and `zoologie''.
No estoy seguro de lo que está pasando. Las cadenas "t / 203tonnement" y "t / 203tonner" no se encuentran en el archivo, aunque se encuentran "t / 203" y "tonnement", pero en líneas separadas que no están contiguas. Lo mismo con "zon / 351s".
Lo que finalmente me funcionó fue:
awk ''!x[$0]++'' /Users/me/Documents/file.txt > /Users/me/Documents/file2.txt
También conservaba palabras cuya única diferencia era el caso, que es lo que quería. No necesitaba la lista ordenada, así que estaba bien que no lo fuera.
Hoy tuve el mismo problema ... una lista de palabras con 238,000 palabras, pero aproximadamente 40, 000 de ellas eran duplicados. Ya los tenía en líneas individuales haciendo
cat filename | tr " " "/n" | sort
Para eliminar los duplicados simplemente hice
cat filename | uniq > newfilename .
Funcionó perfectamente sin errores y ahora mi archivo ha bajado de 1.45MB a 1.01MB
Suponiendo que las palabras son una por línea, y el archivo ya está ordenado:
uniq filename
Si el archivo no está ordenado:
sort filename | uniq
Si no son uno por línea, y no les importa que sean uno por línea:
tr -s [:space:] //n < filename | sort | uniq
Sin embargo, eso no elimina la puntuación, así que quizás quieras:
tr -s [:space:][:punct:] //n < filename | sort | uniq
Pero eso elimina el guión de las palabras con guiones. "man tr" para más opciones.
Supuse que quería que las palabras fueran únicas en una sola línea, en lugar de a lo largo del archivo. Si este es el caso, entonces el script Perl a continuación hará el truco.
while (<DATA>)
{
chomp;
my %seen = ();
my @words = split(m!,/s*!);
@words = grep { $seen{$_} ? 0 : ($seen{$_} = 1) } @words;
print join(", ", @words), "/n";
}
__DATA__
word1, word2, word3, word2, word4, word5, word3, word6, word7, word3
Si desea que el archivo sea único en todo el archivo, solo puede mover el hash %seen
fuera del bucle while (){}
.
Y no olvide la opción -c
para la utilidad uniq
si también está interesado en contar las palabras.
abra el archivo con vim ( vim filename
) y ejecute el comando de ordenación con una marca única ( :sort u
).
ruby -pi.bak -e ''$_.split(",").uniq.join(",")'' filename
?
Admito que los dos tipos de citas son feos.