提取每个第n个正则表达式语句

时间:2013-08-09 12:48:29

标签: regex perl loops

我的文件input.dat如下:

ZZZ 111
ABC 523
ABC 835
ADD 234
ZZZ 222
ABC 0007
2935
ABC 4
ABC 893
wdq
ZZZ 333
ABC 777
ABC 00

我能够在ABC之后提取字符串,但我需要获得每个第n个外观。所以我无法单独区分正则表达式,并认为循环可以处理这个问题。为了获得ABC行上的每一秒条,我试过:

#!/usr/bin/perl
use strict;
use warnings;

my $i;
my @grepped
open(INFILE,"input.dat") or die "$!  Exiting.\n";
while (my $line = <INFILE>) {

    if ($line =~ /^ZZZ (\d+)/){
    push(@grepped,"$1\t")
    };

    $i=0;
    for ($line =~ /^ABC (\d+)/){
    $i+=1;
    if($i==2){ push(@grepped,"$1\n") };
    };
}
close(INFILE);

循环不能正常工作,我不知道为什么。我得到了:

111 523
835
222 0007
4
333 777
00

而不是所需的:

111 835
222 4
333 00

2 个答案:

答案 0 :(得分:3)

将一行与正则表达式匹配不会从输入文件中读取下一行。您必须以某种方式记住循环的每次迭代的状态,例如通过存储您在变量中看到ABC的次数。遇到ZZZ后别忘了把它归零:

my @grepped;
my $seen = 0;
while (my $line = <INFILE>) {
    if ($line =~ /^ZZZ (.*)/) {
        push @grepped, $1;
        $seen = 0;
    }
    if ($line =~ /^ABC (.*)/) {
        push @grepped, $1 if $seen++ == 1;
    }
}

print "$_\n" for @grepped;

另一个选择是读取内循环中的下一行,但是你必须小心不要读过下一个ZZZ。

答案 1 :(得分:1)

我会将数字存储在哈希中并用它们做一些不错的魔法:)

#!/usr/bin/perl
use strict;
use warnings;

my $grepped;
my $active_n;
my $active_l;
while (my $line = <DATA>) {
  chomp $line;
  if ( $line =~ /^ZZZ/ ) {
    $active_l = $line =~ s/^ZZZ //r;
  } elsif ($line =~ /^ABC/) {
    $active_n = $line =~ s/^ABC //r;
  }
  if ($active_l && $active_n) {
      $grepped->{$active_l} = $active_n;
  }  
}

use Data::Dumper;
print map { "$_ => $grepped->{$_}\n"} sort keys $grepped;

__DATA__

ZZZ 111
ABC 523
ABC 835
ADD 234
ZZZ 222
ABC 0007
2935
ABC 4
ABC 893
wdq
ZZZ 333
ABC 777
ABC 00

编辑:

我的输出:

111 => 835
222 => 893
333 => 00