1

我有一个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但我需要每一次出现一次。所以我不能单独用正则表达式来区分,我认为循环可以处理这个问题。为了只在 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
4

2 回答 2

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。

于 2013-08-09T13:01:36.983 回答
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
于 2013-08-09T13:06:34.737 回答