Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/unix/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl 如何打印重复超过六次的文件中的行_Perl_Unix_Awk_Nawk - Fatal编程技术网

Perl 如何打印重复超过六次的文件中的行

Perl 如何打印重复超过六次的文件中的行,perl,unix,awk,nawk,Perl,Unix,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

我有一个包含如下所示数据的文件。第一个逗号分隔的字段可以重复任意次数,我只想打印第六次重复该字段任何值后的行

例如,有八个字段的第一个字段是
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
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
我尝试的是将第2和第3个字段与第1个字段相对应,这样我就可以在
$7
$8
字段上使用
nawk

#!/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
使用awk(filter.awk):

使用:

awk -f filter.awk input_file

假设数据中的点应该是逗号,这个Perl命令将执行您要求的操作

perl -aF, -ne 'print if ++$n{$F[0]} > 6' myfile
输出

$perl-F','-ane'打印,除非$seen{$F[0]}++<6'file.txt
解释

  • -a
    启用自动拆分模式,
    -F','
    指定
    ','
    作为拆分标记,结果列表存储在
    @F
  • -n
    启用隐式逐行循环
  • -e
    以Perl代码的形式执行以下参数(
    “…”
  • %seed
    跟踪第一个字段的显示次数

如果您特别想要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);
#/usr/bin/perl
严格使用;
使用警告;
我的$count=0;
我的$prev=“”;
打开(MYFILE,'temp');
而(){
my@a=拆分(/,/);
如果($prev==$a[0])
{
$count++;
如果($count>6)
{
打印“$”;
}
}
其他的
{
$prev=$a[0];
$count=1;
}
}
关闭(MYFILE);
如果您的记录无序 i、 e.您的输入中可能会随机分布“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脚本由一系列
条件{action;}
块组成。如果缺少条件,则对每一行应用操作。如果动作缺失,则暗示为
print。因此,只包含一个条件的awk脚本将打印该条件计算为true的每个输入行

在这种情况下,我们的条件也包含动作的元素。它增加了关联数组中的元素,其中键是第一个字段。无论条件的计算结果是否为true,增量都会发生。此外,将
++
放在变量前面而不是后面会导致增量发生在求值之前而不是之后。(我说的是
++var
var++
之间的区别)如果结果递增的数组元素大于6,则条件求值为true,从而导致打印行

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

如果您的记录已订购 i、 e.您所有的“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,则打印行(隐式)

这样做的优点是不消耗数组的内存,但仅当您的目标是将连续的行集合与公共$1匹配,而不是处理可能随机分布在整个输入中的匹配行时,才适用。

我只是将第二个和第三个字段与第一个字段进行转置,这样我就可以在7美元或8美元的范围内工作了/usr/bin/ksh awk-F“,“{a[$1];b[$1]=b[$1]”,“$2C[$1]=c[$1]”,“$3}END{for(i in a){print i”,“b[i],“c[i]}”file>output.txt请不要在评论中发布代码;改为编辑您的问题。我在您的数据或代码中未看到任何字段
$7
$8
。为什么此问题已关闭?它描述了一个问题,提供了输入数据、预期结果和OP的尝试。实际上,似乎比我见过的许多问题都好。如果解决方案正确,为什么要投反对票?博罗丁,我在发布时没有注意到你的答案,对此表示抱歉!这仅在记录已排序的情况下有效。不管怎样,戈蒂的答案都是有效的。你的作品只有在记录被订购的情况下才有效——ghoti的作品无论它们是否被订购,因此它更灵活。但是his的缺点是在数组中积累数据,这对于非常大的输入可能是一个问题。IMHO,根据给定的示例和措辞,减少无序重复是不正确的。我想我们需要OP的澄清!)@丹尼斯·威廉姆森:不-
$seen{$F[0]}++
在第一次通过时将
0
<代码>0
5
包含六个元素。
$ awk -F, '++a[$1] > 6' input.txt
1111111,gggggggg,14
1111111,hhhhhhhh,14
2222222,gggggggg,14
3333333,gggggggg,14
3333333,hhhhhhhh,14
$ 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