2

我试图在一个数组中找到两个模式并将结果放入另一个数组中。

例如

  $/ = "__Data__";

  __Data__
  #SCSI_test         # put this line into  @arrayNewLines      
  kdkdkdkdkdkdkdkd
  dkdkdkdkdkdkdkdkd
  - ccccccccccccccc  # put this line into @arrayNewLines

代码

    while(<FILEREAD>)
    {
          chomp;
          my @arrayOld = split(\n,@array);

          foreach my $i (0 .. $#arrayOld)
          {
                if($arrayOld[$i] =~ /^-(.*)/g or /\#(.*)/g)
                {
                     my @arrayNewLines = $arrayOld[$i];
                     print "@arrayNewLines\n";
                }
          }
    }

此代码仅打印出 ccccccccccccccc 但我希望它输出 ccccccccccccccc #SCSI_test

4

2 回答 2

1

该代码不只是打印cccccc...,它会打印所有内容。你的问题是这一行:

if($arrayOld[$i] =~ /^-(.*)/g or /\#(.*)/g) {

你在这里做的是先检查$arrayOld[$i]然后检查$_,因为/\#(.*)/它是 perl 的简写$_ =~ /\#(.*)/。由于该行包含一个哈希字符#,它将始终匹配,并且该行将始终打印。

您的行相当于:

if(   $arrayOld[$i] =~ /^-(.*)/g 
      or 
      $_ =~ /\#(.*)/g) {

答案是加入正则表达式:

if($arrayOld[$i] =~ /^-|#/) {

但是,在那之后您的代码远非干净......从顶部开始:

如果将输入记录分隔符设置$/为该__Data__输入,您将获得两条记录(Data::Dumper输出如下所示):

$VAR1 = '__Data__';
$VAR1 = '
#SCSI_test         # put this line into  @arrayNewLines
kdkdkdkdkdkdkdkd
dkdkdkdkdkdkdkdkd
- ccccccccccccccc  # put this line into @arrayNewLines
';

当您chomp记录时,您将从末尾删除__Data__,因此第一行将变为空。因此,从本质上讲,您将始终拥有一个领先的空白字段。这没什么可怕的,但要记住的事情。

你的split说法是错误的。首先,第一个参数应该是一个正则表达式:/\n/。第二个参数应该是一个标量,而不是一个数组。split(/\n/,@array)将评估为split(/\n/, 2),因为该数组在标量上下文中并返回其大小而不是其元素。

此外,当然,由于您正在循环读取FILEREAD句柄中的行,因此该@array数组将始终包含相同的数据,并且与文件句柄中的数据无关。你想要的是:split /\n/, $_.

这个循环:

foreach my $i (0 .. $#arrayOld) {

对于这个问题,不是一个很好的循环结构。此外,不需要使用中间数组。只需使用:

for my $line (split /\n/, $_) {

当你这样做

my @arrayNewLines = $arrayOld[$i];
print "@arrayNewLines\n";

您将整个数组设置为标量,然后打印它,这完全是多余的。您只需直接打印标量即可获得相同的效果。

您的代码应如下所示:

while(<FILEREAD>) {
    chomp;
    foreach my $line (split /\n/, $_) {
        if($line =~ /^-|#/) {
            print "$line\n";
        }
    }
}

还建议您使用词法文件句柄,因此而不是

open FILEREAD, "somefile" or die $!;       # read with <FILEREAD>

采用:

open my $fh, "<", "somefile" or die $!;    # read with <$fh>
于 2012-05-25T17:48:30.753 回答
0
#! /usr/bin/env perl

use strict;
use warnings;

*ARGV = *DATA;

my @arrayNewLines;

while (<>) {
  chomp;

  if (/^-(.*)/ || /\#(.*)/) {
    push @arrayNewLines, $_;
  }
}

print "$_\n" for @arrayNewLines;

__DATA__
#SCSI_test         # put this line into  @arrayNewLines
kdkdkdkdkdkdkdkd
dkdkdkdkdkdkdkdkd
- ccccccccccccccc  # put this line into @arrayNewLines

更好的是,如果您有 5.10 或更高版本,请使用智能匹配。

#! /usr/bin/env perl

use strict;
use warnings;

use 5.10.0;  # for smart matching

*ARGV = *DATA;

my @arrayNewLines;

my @patterns = (qr/^-(.*)/, qr/\#(.*)/);

while (<>) {
  chomp;
  push @arrayNewLines, $_ if $_ ~~ @patterns;
}

print "$_\n" for @arrayNewLines;

__DATA__
#SCSI_test         # put this line into  @arrayNewLines
kdkdkdkdkdkdkdkd
dkdkdkdkdkdkdkdkd
- ccccccccccccccc  # put this line into @arrayNewLines

无论哪种方式,输出都是

#SCSI_test # 将此行放入@arrayNewLines
- ccccccccccccccc # 将此行放入@arrayNewLines
于 2012-05-25T16:24:02.857 回答