我有一个包含以下数据的文件。第一个以逗号分隔的字段可以重复任意次,并且我想在第六次重复此字段的任何值后仅打印行
例如,有八个字段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
输出:
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
我试过的是转发第1个第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
答案 0 :(得分:7)
即。您可以在整个输入中随机分配“1111111”项目:
$ awk -F, '++a[$1] > 6' input.txt
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
这是如何运作的?
如您所知,awk的-F
选项设置分隔符。如果它不是一个特殊的角色,就没有必要引用它。
Awk脚本由一系列condition { action; }
块组成。如果缺少条件,则对每一行应用操作。如果缺少该操作,则隐含为print;
。因此,仅包含条件的awk脚本将打印该条件评估为真的每个输入行。
在这种情况下,我们的条件也包含一个动作的元素。它,它增加了一个关联数组的元素,其中键是你的第一个字段。无论条件是否为真,都会发生增量。此外,将++
提前而不是跟随变量会导致增量在评估之前发生而不是之后 / em>它。 (我在谈论++var
和var++
之间的区别。)如果结果递增的数组元素大于6,则条件计算结果为true,导致行打印。
这在功能上等同于其他答案中的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
这是如何运作的?
这样做的好处是不会使用数组占用内存,但只有当你的目标是使用常见的$ 1匹配顺序的行集而不是处理可能在整个输入中随机分布的匹配行时,它才适用。
答案 1 :(得分:6)
$ perl -F',' -ane 'print unless $seen{ $F[0] }++ < 6' file.txt
<强>解释强>
-a
启用自动分段模式,-F','
指定','
作为拆分令牌,结果列表存储在@F
中作为结果-n
启用隐式逐行循环-e
执行以下参数(在本例中为'...'
)作为Perl代码%seen
跟踪第一个字段的显示次数答案 2 :(得分:4)
假设数据中的点应该是逗号,这个Perl命令将执行您所要求的
perl -aF, -ne 'print if ++$n{$F[0]} > 6' myfile
<强>输出强>
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
答案 3 :(得分:1)
使用awk(filter.awk):
BEGIN { FS = "[,.]" }
o == $1 { cnt++ }
o != $1 { o=$1; cnt = 0; }
cnt >= 6 { print $0 }
使用:
awk -f filter.awk input_file
答案 4 :(得分:0)
如果您想特别使用awk解决方案,请点击此处:
awk -F, '{if(seen==$1){count++;}else{seen=$1;count=1}if(count>6)print }' file
测试如下:
> awk -F, '{if(seen==$1){count++;}else{seen=$1;count=1}if(count>6)print }' temp
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
如果您需要perl脚本,请参阅下文:
#!/usr/bin/perl
use strict;
use warnings;
my $count=0;
my $prev="";
open (MYFILE, 'temp');
while (<MYFILE>) {
my @a=split(/,/);
if($prev==$a[0])
{
$count++;
if($count>6)
{
print "$_";
}
}
else
{
$prev=$a[0];
$count=1;
}
}
close (MYFILE);