2010-04-12 9 views
1

i dispose d'un fichier comme celui-ci:Permutation des colonnes dans un fichier et supprimer les doublons

term1 term2 
term3 term4 
term2 term1 
term5 term3 
..... ..... 

ce que je dois faire est de supprimer les doublons dans un ordre dans lequel ils apparaissent, tels que:

term1 term2 

et

term2 term1 

est un doublon pour moi. C'est un fichier très long, donc je ne suis pas sûr de ce qui peut être plus rapide. Est-ce que quelqu'un a une idée sur la façon de faire cela? awk peut-être?

Répondre

1

La commande de chaque mot dans la ligne et le tri est facile avec perl.

./scriptbelow.pl < datafile.txt | uniq

#!/usr/bin/perl 

foreach(sort map { reorder($_) } <>) { 
    print; 
} 

sub reorder { 
    return join(' ', sort { $a cmp $b } split(/\s+/, $_)) . "\n"; 
} 
1

En perl:

while($t=<>) { 
@ts=sort split(/\s+/, $t); 
$t1 = join(" ", @ts); 
print $t unless exists $done{$t1}; 
$done{$t1}++; 
} 

Ou:

cat yourfile | perl -n -e 'print join(" ", sort split) . "\n";' | sort | uniq 

Je ne suis pas sûr que l'on obtient de meilleurs résultats pour les fichiers énormes. Le premier produit une énorme hashmap perl en mémoire, le second invoque une commande "sort" ...

1

Pour préserver la commande d'origine, une solution simple (mais pas forcément rapide et/ou économe en mémoire) dans awk:

awk '!seen[$1 " " $2] && !seen[$2 " " $1] { seen[$1 " " $2] = 1; print } 

Edit: tri alternative ruby:

ruby -n -e 'puts $_.split.sort.join(" ")' | sort | uniq 
1

Si le fichier est très très longue, peut-être vous devriez envisager d'écrire votre programme avec C/C++. Je pense que ce serait la solution la plus rapide (surtout si vous devez traiter tout le fichier pour chaque ligne que vous lisez). Le traitement avec des fonctions de bash obtenir très lent avec de gros fichiers et des opérations répétitives

1

Si vous souhaitez supprimer les deux « terme1 terme2 » et « terme2 terme1 »:

join -v 1 -1 1 <(sort input_file) -v 2 -2 2 <(sort -k 2 input_file) | uniq 
1
awk '($2FS$1 in _){ 
delete _[$1FS$2];delete _[$2FS$1] 
next 
} { _[$1FS$2] } 
END{ for(i in _) print i } ' file 

sortie

$ cat file 
term1 term2 
term3 term4 
term2 term1 
term5 term3 
term3 term5 
term6 term7 

$ ./shell.sh 
term6 term7 
term3 term4 
1

La façon dont je le ferais (si vous n'avez pas besoin de garder les doubles colonnes) est:

sed 's/ /\n/g' test.txt | sort -u 

Voici ce que la sortie ressemble à (ignorer mon message funky):

[~] 
==> cat test.txt 
term1 term2 
term3 term4 
term2 term1 
term5 term3 
[~] 
==> sed 's/ /\n/g' test.txt | sort -u 
term1 
term2 
term3 
term4 
term5 
Questions connexes