2
votes

Commande Shell pour réduire les données tabulaires pour créer une colonne non redondante

J'ai des données tabulaires qui ressemblent à ceci.

$ perl -e '%seen = (); for (<>) { @v = split(/\s+/); unless (exists($seen{$v[1]})) { $seen{$v[1]} = 1; print } }' < data.tsv > data.clean.tsv

Je dois supprimer des lignes du tableau afin qu'aucune valeur ne soit dupliquée dans la deuxième colonne (date) - seulement la première l'occurrence doit rester.

Je n'ai pas utilisé Perl depuis un certain temps, mais après quelques recherches sur Google pour me rappeler la syntaxe correcte, j'ai pu trouver cette ligne unique.

1f2edc31defc588a369544ac32215afec2ae65da  2019-01-08
e95c31b76be6b99eb8a0670b93b91c9e9abf2efb  2018-11-27
c2dd1d6be6434b6ef109fa0394546fa500501efe  2018-11-27
c6b6b534addff919150d94276f61eb8d0882f3f6  2018-09-04
459a495a929cffa2205d31c6cc7ba2750af2580b  2018-06-25
11f7883b29295e39bc964522deb96132d6a2803e  2018-06-25
73a2a72ee9d0a9acf0ed02b0959f3fb5a44c3fc7  2018-06-25
0970c0fef779a4ea89638140f339c2047d10d0c5  2017-12-29

Après un rapide coup d'œil, cela semble faire l'affaire, mais c'est un gâchis. Y a-t-il un moyen plus propre et plus concis de faire cela en utilisant des commandes shell portables (UNIX), ou une solution va-t-elle impliquer un désordre de Perl / sed / awk / etc.


1 commentaires

Veuillez inclure la sortie souhaitée.


3 Réponses :


1
votes

Perl a anticipé des problèmes comme celui-ci et a proposé des solutions concises:

$ perl -MO=Deparse -ane 'print unless $seen{$F[1]}++' 
LINE: while (defined($_ = <ARGV>)) {
    our(@F) = split(' ', $_, 0);
    print $_ unless $seen{$F[1]}++;
}
-e syntax OK

Voir perlrun pour plus d'informations sur les commutateurs -a et -n .

Avec le Module B :: Deparse , vous pouvez voir comment Perl étend les commutateurs de ligne de commande en quelque chose qui ressemble à votre script d'origine.

perl -ane 'print unless $seen{$F[1]}++' < data.csv > data.clean.csv


0 commentaires

2
votes

Pas besoin d'être en désordre

perl -ne'print unless $exists{(split)[1]}++' dup_data.txt


0 commentaires

1
votes

Puisque data.tsv est déjà trié sur le champ 2nd , une méthode plus simple, pas de perl nécessaire:

1f2edc31defc588a369544ac32215afec2ae65da  2019-01-08
e95c31b76be6b99eb8a0670b93b91c9e9abf2efb  2018-11-27
c6b6b534addff919150d94276f61eb8d0882f3f6  2018-09-04
459a495a929cffa2205d31c6cc7ba2750af2580b  2018-06-25
0970c0fef779a4ea89638140f339c2047d10d0c5  2017-12-29


1 commentaires

Utilisation de bash pour comparer au code OP: cmp <(perl -e '% vu = (); for (<>) {@v = split (/ \ s + /); sauf (existe ($ vu {$ v [1]})) {$ vu {$ v [1]} = 1; print}} ', qui renvoie 0 ( i.e. true, les sorties sont les mêmes).