为什么捕获的表达式的第一个值存储在Perl的第四个元素中?

时间:2009-08-02 01:20:25

标签: perl arrays

我将正则表达式捕获的信息存储到数组中。但由于某种原因,第一个值存储在数组的4个元素。关于什么是错误以及如何将第一个值存储在数组的第一个元素中的任何建议。

以下是脚本:

#!/usr/bin/perl

use strict;
my @value;
my $find= qr/^\s+([0-9]+)\s+([A-Z])/;

open (FILE, "</usr/test")|| die "cant open file";
my @body=<FILE>;

foreach my $line (@body){
    chomp $line;
    push @value, join('', $line =~ /$find/);
}
print "$value[0]\n"; #does not print anything
print "$value[4]\n"; #prints first value i.e 1389E
exit;

DATA

   1389 E not
   188  S yes
   24   D yes
   456  K not
   2    Q yes   

4 个答案:

答案 0 :(得分:4)

您的第二行在数字组和字母之间有多个空格,因此您可能希望\s+两次而不是\s第二次。

您最终不一定知道@value数组中有多少项,因此您可能希望将打印放入for循环而不是假设您有第五项。 (也许你知道你想要第一个和第五个?但是后续:根据你的编辑,你毕竟有两个以上的条目。我在下面给出的版本,使用split\s+来捕获所有行的数字和字母。我将调整脚本的打印部分以向您显示我的意思。

其他一些事情:

  • 您应始终启用警告。
  • 没有理由将整个文件读入数组,然后逐行处理。跳过@body数组,然后在while循环中执行您需要的操作。
  • 使用更现代的open形式的词法文件句柄和三个参数。
  • split对我来说似乎更直接,而不是带有捕获的正则表达式。由于您要捕获该行的两个特定部分,因此您可以使用带有数组切片的split来抓取这两个项目并将其提供给join
  • @value不是一个特别有用的变量名称,但我认为你应该至少使它复数。我认为,这是一个很好的习惯,因为数组存储了你的复数记录。 (这不是一个严格的规则,但它在这里给我带来了麻烦。这一点非常小。)

以下是这些看起来的样子:

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

    my @values;

    # open my $filehandle, '<', '/usr/test'
    #     or die "Can't open /usr/test: $!";

    while (my $line = <DATA>) {
        chomp $line;
        push @values, join('', (split /\s+/, $line)[1..2]);
    }

   for my $record (@values) {
      print $record, "\n";
    }

    __DATA__
       1389 E not
       188  S yes
       24   D yes
       456  K not
       2    Q yes

答案 1 :(得分:1)

我认为你应该写作

print "$value[0]\n";
print "$value[4]\n";

访问数组的元素。

答案 2 :(得分:1)

你应该使用词法文件句柄和open的三个参数形式,以及避免不必要地诋毁文件。

在任何情况下,问题的最可能原因是模式中缺少单个字符。将下面的一个与您上面的那个进行比较。

#!/usr/bin/perl

use strict;
use warnings;

my @value;
my $find= qr/^\s+([0-9]+)\s+([A-Z])/;

while ( my $line = <DATA> ) {
    last unless $line =~ /\S/;
    push @value, join '', $line =~ $find;
}

use Data::Dumper;
print Dumper \@value;

__DATA__
   1389 E not
   188  S yes
   24   D yes
   456  K not
   2    Q yes

答案 3 :(得分:0)

您的数据中是否有前导空格行或其他前导行与正则表达式不匹配?由于无条件地推送()输入到输出数组,无论你的正则表达式是否匹配,你都会得到输入中每个不匹配行的空白数组元素。

观察:

#!/usr/bin/perl

use strict;
use warnings;

my @lines;

while (<DATA>) {
  push @lines , ( join( '' , /^\s*(\d+)/ ));
}

foreach ( 0 .. $#lines ) {
  print "$_ -> $lines[$_]\n";
}


__DATA__
FOO
Bar
Baz
   1234
456
bargle

输出:

0 -> 
1 -> 
2 -> 
3 -> 1234
4 -> 456
5 ->