Shell命令折叠表格数据以创建非冗余列

时间:2019-01-10 20:48:38

标签: shell perl

我有一些像这样的表格数据。

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

我需要从表中删除行,以便在第二(日期)列中没有重复的值-仅应保留第一次出现的情况。

我已经有一段时间没有使用Perl了,但是经过几个Google搜索以提醒自己正确的语法后,我才提出了这种单行代码。

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

乍一看,这似乎可以解决问题,但这是一团糟。是否有一种更简洁的方法来使用可移植(UNIX)Shell命令来执行此操作,或者是否有任何解决方案都涉及到Perl / sed / awk / etc等问题?

3 个答案:

答案 0 :(得分:2)

不需要凌乱

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

答案 1 :(得分:1)

Perl预料到了这样的问题,并提出了简洁的解决方案:

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

有关-a-n开关的信息,请参见perlrun

借助有用的B::Deparse模块,您可以了解Perl如何将命令行开关扩展为类似于原始脚本的内容。

$ 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

答案 2 :(得分:1)

由于 data.tsv 已经在 2nd 字段上进行了排序,这是一种更简单的方法,因此不需要perl

uniq -f 1 data.tsv > data.clean.tsv

输出,( data.clean.tsv 的内容):

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