web-dev-qa-db-fra.com

Comment supprimer les mots en double d'un fichier texte en utilisant la commande linux

J'ai un fichier texte avec des mots séparés par une virgule, par exemple:

Word1, Word2, Word3, Word2, Word4, Word5, Word 3, Word6, Word7, Word3

je veux supprimer les doublons et devenir:

Word1, Word2, Word3, Word4, Word5, Word6, Word7

Des idées? Je pense que egrep peut m'aider, mais je ne suis pas sûr de savoir comment l'utiliser exactement ....

18
cupakob

En supposant que les mots sont un par ligne et que le fichier est déjà trié:

uniq filename

Si le fichier n'est pas trié:

sort filename | uniq

Si ce n'est pas un par ligne et que cela ne vous dérange pas d'en avoir un par ligne:

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

Cela ne supprime pas la ponctuation, alors peut-être que vous voulez:

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

Mais cela supprime le trait d'union des mots composés. "homme tr" pour plus d'options.

30
Randy Orrison

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

J'admets que les deux types de citations sont laids.

3
Oliver N.

La création d'une liste unique est assez facile grâce à uniq, bien que la plupart des commandes Unix veuillent une entrée par ligne au lieu d'une liste séparée par des virgules. Nous devons donc commencer par la convertir:

$ sed 's/, /\n/g' filename | sort | uniq
Word1
Word2
Word3
Word4
Word5
Word6
Word7

La partie la plus difficile consiste à réinscrire ceci sur une ligne avec des virgules comme séparateurs et non des séparateurs. J'ai utilisé un Perl one-liner pour le faire, mais si quelqu'un a quelque chose de plus idiomatique, modifiez-moi. :)

$ sed 's/, /\n/g' filename | sort | uniq | Perl -e '@a = <>; chomp @a; print((join ", ", @a), "\n")'
Word1, Word2, Word3, Word4, Word5, Word6, Word7
2
Ryan Bright

Voici un script awk qui laissera chaque ligne intacte, ne supprimant que les mots dupliqués:

BEGIN { 
     FS=", " 
} 
{ 
    for (i=1; i <= NF; i++) 
        used[$i] = 1
    for (x in used)
        printf "%s, ",x
    printf "\n"
    split("", used)
} 
2
mamboking

j'ai eu le même problème aujourd'hui .. une liste de mots avec 238 000 mots, mais environ 40 000 étaient des doublons. Je les avais déjà en lignes individuelles en faisant

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

pour supprimer les doublons je l'ai simplement fait 

cat filename | uniq > newfilename .

A fonctionné parfaitement aucune erreur et maintenant mon fichier est en baisse de 1,45 Mo à 1,01 Mo

2
Biffinum

J'ai supposé que vous vouliez que les mots soient uniques sur une seule ligne plutôt que dans tout le fichier. Si tel est le cas, le script Perl ci-dessous fera l'affaire.

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 vous voulez que le fichier soit unique, vous pouvez simplement déplacer le hachage %seen en dehors de la boucle while (){}.

1
Beano

Je suis tombé sur ce fil en essayant de résoudre à peu près le même problème. J'avais concaténé plusieurs fichiers contenant des mots de passe, il y avait donc beaucoup de doublons. En outre, de nombreux caractères non standard. Je n'avais pas vraiment besoin qu'ils soient triés, mais il me semblait que cela allait être nécessaire pour uniq.

J'ai essayé:

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'

A tenté:

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'.

Et même essayé de passer par chat en premier, juste pour que je puisse voir si nous obtenions une entrée appropriée.

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'.

Je ne suis pas sûr de ce qui se passe. Les chaînes "t\203tonnement" et "t\203tonner" ne figurent pas dans le fichier, bien que "t/203" et "tonnement" se trouvent, mais sur des lignes séparées non adjacentes. Même chose avec "zon\351s".

Ce qui a finalement fonctionné pour moi a été:

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

Cela préservait également des mots dont la seule différence était la casse, ce que je voulais. Je n'avais pas besoin que la liste soit triée, donc c'était bien qu'elle ne l'était pas.

1
sudon't

Je pense que vous voudrez remplacer les espaces par des nouvelles lignes, utilisez la commande uniq pour rechercher des lignes uniques, puis remplacez les nouvelles lignes par des espaces.

1
Paul Sonier

Et n'oubliez pas l'option -c pour l'utilitaire uniq si vous souhaitez également obtenir un décompte des mots.

0
Rob Wells

ouvrir le fichier avec vim (vim filename) et exécuter la commande de tri avec un indicateur unique (:sort u).

0
meysam