如何从重复六次以上的文件中打印行

Mik*_*ike 3 unix perl awk nawk

我有一个包含下面显示的数据的文件.第一个以逗号分隔的字段可以重复任意次,并且我想在第六次重复此字段的任何值后仅打印行

例如,有八个字段1111111作为第一个字段,我想只打印这些记录的第七个和第八个

输入文件:

1111111,aaaaaaaa,14
1111111,bbbbbbbb,14
1111111,cccccccc,14
1111111,dddddddd,14
1111111,eeeeeeee,14
1111111,ffffffff,14
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,aaaaaaaa,14
2222222,bbbbbbbb,14
2222222,cccccccc,14
2222222,dddddddd,14
2222222,eeeeeeee,14
2222222,ffffffff,14
2222222,gggggggg,14
3333333,aaaaaaaa,14
3333333,bbbbbbbb,14
3333333,cccccccc,14
3333333,dddddddd,14
3333333,eeeeeeee,14
3333333,ffffffff,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
Run Code Online (Sandbox Code Playgroud)

输出:

1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
Run Code Online (Sandbox Code Playgroud)

我试过的是相对于1st转换第2和第3个字段,以便我可以nawk$7或的字段上使用$8

#!/usr/bin/ksh awk -F"," '{ a[$1]; b[$1]=b[$1]","$2 c[$1]=c[$1]","$3} END{ for(i in a){ print i","b[i]","c[i]} } ' file > output.txt
Run Code Online (Sandbox Code Playgroud)

gho*_*oti 7

如果您的记录无序

即您可能在整个输入中随机分配"1111111"项:

$ awk -F, '++a[$1] > 6' input.txt
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?

如您所知,awk的-F选项设置分隔符.如果它不是一个特殊的角色,那么就没有必要引用它.

Awk脚本由一系列块组成condition { action; }.如果缺少条件,则对每一行应用操作.如果缺少该行动,则暗示是print;.因此,仅由条件组成的awk脚本将打印该条件评估为true的每个输入行.

在这种情况下,我们的条件也包含一个动作的元素.它,它增加了一个关联数组的元素,其中键是你的第一个字段.无论条件是否为真,都会发生增量.此外,++ 提前而不是跟随变量会导致增量在评估之前而不是之后发生.(我说的之间的差值++varvar++).而且,如果将得到的递增数组元素是大于6,该条件评估为真,使得所述线打印.

这在功能上等同perl于其他答案中的解决方案,但由于awk脚本的性质更加严格且(可以说)更简单.当然,它可能会更快.(在我刚才的非正式测试中,上面的awk脚本的执行速度是另一个答案的等效perl脚本的两倍多,在0.23s的用户时间内处理250000行输入,而perl则处理0.61秒.)

如果您的记录是订购的

即你所有的"1111111"线都在一起:

$ awk -F, '$1!=f{c=0;f=$1} ++c>6' input.txt
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
Run Code Online (Sandbox Code Playgroud)

这是如何运作的?

  • 如果我们与上次不同的$ 1(在第一行也是如此),我们重置计数器并将$ 1保存到变量以供将来比较.
  • 然后,如果计数器超过6,我们递增计数器并打印行(隐式).

这样做的好处是不会使用数组占用内存,但只有当您的目标是将常规$ 1的连续行集匹配,而不是处理可能随机分布在整个输入中的匹配行时,它才适用.


Zai*_*aid 6

$ perl -F',' -ane 'print unless $seen{ $F[0] }++ < 6' file.txt
Run Code Online (Sandbox Code Playgroud)

说明

  • -a启用autosplit模式,-F','指定','为拆分令牌,结果列表@F作为结果存储
  • -n 启用隐式逐行循环
  • -e执行以下参数('...'在本例中)作为Perl代码
  • %seen 跟踪第一个视野被看到的次数