我知道必须有一个perl
单一的回应。在这里 - 没有经过严格测试,所以请注意购买者 ;-)
perl -anE 'push @AoA,[@F]; $S{$_}++ for @F[0];}{for $i (0..$#AoA) {for $j (grep {$S{$_}==1} keys %S) {say "@{$AoA[$i]}" if @{$AoA[$i]}[0]==$j}}' data.txt
这种方法的缺点是它以稍微修改的格式输出数据(我认为这很容易修复)并且它使用两个for
循环和一个“蝴蝶运算符”(!!)它还使用grep()
(它引入了一个隐式循环- 即即使您不必自己编写循环也可以运行代码),因此它可能会很慢,有 150 万条记录。我希望看到它与awk
虽然相比uniq
。
从好的方面来说,它不使用任何模块,应该可以在 Windows 和 OSX 上运行。当有几十个具有唯一第一列的相似记录并且不需要在检查唯一行之前对输入进行排序时,它就可以工作。该解决方案主要摘自Joseph Hall、Joh McAdams 和brian d foy在Effective Perl Programming结尾处的单行示例 (一本很棒的书——当聪明的比赛和尘埃落定时,我希望新版本出现):~~
given when
这是(我认为)它的工作原理:
- 因为我们正在使用
-a
我们免费获得@F
数组所以使用它而不是拆分
- 因为我们使用的是
-n
我们在一个while() {}
循环中,所以intopush
的元素作为匿名引用数组(充当“匿名数组构造函数”)。这样他们就会闲逛,我们以后可以参考他们(这甚至有意义吗???)@F
@AoA
[]
- 使用上面提到的书中的
$seen{$_}++
习语(我们使用$S
而不是$seen
),并由@Axeman 在这里对 SO进行了很好的描述@F[0]
,%S
根据我们看到一个元素的次数(或行)具有给定值(即行内容)。
- 使用“蝴蝶”
}{
突破while
然后,在一个单独的块中,我们使用两个for
循环遍历外部数组并检查每个元素(它们本身是匿名数组$i
- 每行一个),然后,对于每个内部匿名数组,在我们之前创建的散列(或内部循环)中与等于“1”的grep
值一起使用,并将这些值连续放入.keys
%S
for $j (grep {$S{$_}==1} keys %S)
$j
- 最后,我们遍历外部数组并打印任何匿名数组,其中该数组的第一个元素等于每个 (
$j
) 的值。我们这样做:(@{$AoA[$i]}[0]==$j
)。
awk
在@Kent 的手中更简洁一些。如果有人对如何缩短或记录我的“线路噪音”有任何建议(我从来没有说过perl
!)请添加建设性意见!
谢谢阅读。