2009-06-04 72 views
17

Tengo un archivo de texto plano con las palabras, que están separados por una coma, por ejemplo:Cómo eliminar palabras duplicadas de un archivo de texto plano usando comandos de Linux

word1, word2, word3, word2, word4, word5, word 3, word6, word7, word3 

quiero eliminar los duplicados y convertirse :

word1, word2, word3, word4, word5, word6, word7 

¿Alguna idea? Creo que, egrep puede ayudarme, pero no estoy seguro, cómo usarlo exactamente ...

+1

¿Desea que las palabras sean únicas en línea o en todo el archivo? Además, ¿desea mantener el orden original de las palabras, o está contento si se cambia el orden? – Beano

+0

necesito las palabras únicas en todo el archivo. el orden de las palabras no es importante. – cupakob

+0

Vea también: [¿Cómo puedo encontrar palabras repetidas en un archivo usando grep/egrep?] (Http://stackoverflow.com/q/33396629/562769) –

Respuesta

28

Suponiendo que las palabras son una por línea, y el archivo ya está ordenado:

uniq filename 

Si el archivo no está ordenada:

sort filename | uniq 

Si no son una por línea, y no le importa ellos es una línea por:

tr -s [:space:] \\n < filename | sort | uniq 

Eso no quita puntuacion, sin embargo, lo que tal vez desee :

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.

+0

que funciona para mí :) muchas gracias ... solo necesito poner todas las palabras en una fila con: cat testfile_out.txt | tr "\ n" ""> testfile_out2.txt – cupakob

+10

"ordenar -u" eliminaría la necesidad de uniq – Beano

1

Creo que querrás reemplazar los espacios por líneas nuevas, usa el comando uniq para encontrar un único líneas, luego reemplace las líneas nuevas con espacios de nuevo.

+0

uniq solo compara las líneas adyacentes para que esto no funcione. – Beano

+0

cuando se combina con el género – Jonik

3

ruby -pi.bak -e '$_.split(",").uniq.join(",")' filename?

Admitiré que los dos tipos de citas son feas.

+2

¡Ruby no es un comando de Linux! Supongo que por comando de Linux quiere decir programas regulares de GNU. – Danny

+0

@Danny, lo vi, y puedes hacerlo con un poco de alquimia sed/awk exagerada, pero realmente creo que este es un trabajo para un lenguaje de scripting. –

+0

+1, ya que esto parece innegablemente elegante, y más accesible para los mortales en comparación con Perl one-liner de Igor Krivokon :) – Jonik

1

Supuse que deseaba que las palabras fueran únicas en una sola línea, en lugar de en todo el archivo. Si este es el caso, entonces el siguiente script de Perl 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 singularidad durante todo el archivo, sólo se puede mover el hash %seen fuera del bucle while(){}.

+2

¡Perl no es un comando de Linux! Supongo que por comando de Linux quiere decir programas regulares de GNU. Entonces Perl está instalado en todas partes ... je. – Danny

+0

¿Podría indicar cuál es su definición de "comando Linux" (o mejor dicho @brbright como usted parece conocerlo)? Tal vez un comando encontrado en las distribuciones de Linux? – Beano

+0

me refiero a un comando, que está integrado en la instalación predeterminada de las distribuciones más populares ... por ejemplo algo así como grep. – cupakob

2

Creación de una lista única es muy fácil gracias a uniq, aunque la mayoría de los comandos UNIX como una entrada por línea en lugar de una lista separada por comas, por lo que tenemos que empezar mediante la conversión a que:

$ 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. Usé un trazador de líneas Perl para hacer esto, pero si alguien tiene algo más idiomático, por favor edítame. :)

$ sed 's/, /\n/g' filename | sort | uniq | perl -e '@a = <>; chomp @a; print((join ", ", @a), "\n")' 
word1, word2, word3, word4, word5, word6, word7 
+0

tr "" "\ n" podría ser más eficiente que sed en este caso – florin

+0

y que también está funcionando – cupakob

+0

Poner eso en una línea es bastante simple: sed 's /,/\ n/g' filename | ordenar | pegar -s -d, | sed 's /, /,/g' el comando es pega, ¡muy bueno! – Mapio

0

Y no se olvide de la opción -c para la utilidad uniq si usted está interesado en obtener un recuento de las palabras también.

2

Aquí es un script awk que dejará a cada línea en el tacto, solamente la eliminación de 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) 
} 
+0

que funciona también, pero no es perfecto;) el resultado contiene una palabra con dos comas ... eso no es un gran problema :) muchas gracias – cupakob

1

encontramos con este hilo, mientras trata de resolver tanto 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.

me trataron:

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' 

intentado:

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 trató de pasarla a través de gato en primer lugar, sólo para poder ver si nos iban a dar 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 qué 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 funcionó para mí fue:

awk '!x[$0]++' /Users/me/Documents/file.txt > /Users/me/Documents/file2.txt 

It palabras también conservados cuya única diferencia era el caso, que es lo que quería. No necesité la lista ordenada, por lo que estaba bien que no fuera así.

1

tuve el mismo problema hoy .. una lista de palabras con 238,000 palabras, pero alrededor de 40, 000 de esos fueron duplicados. Ya los tenía en líneas individuales haciendo

cat filename | tr " " "\n" | sort 

para eliminar los duplicados Yo simplemente hice

cat filename | uniq > newfilename . 

funcionado perfectamente sin errores y ahora mi archivo es desde 1.45MB 1.01MB a

0

abra el archivo con vim (vim filename) y ejecute el comando de ordenación con distintivo único (:sort u).

Cuestiones relacionadas