Perl IF语句不匹配REGEX中的变量

时间:2012-08-01 12:50:43

标签: perl

my $pointer = 0;
foreach (@new1)
{
       my $test = $_;
       foreach (@chk)
       {
               my $check = $_;
               chomp $check;
               delete($new1[$pointer]) if ($test =~ /^$check/i);
       }
       $pointer++;
}

if语句永远不会匹配@ new1数组中的许多条目在数组元素的开头包含$ check的事实(至少88)。 我不确定它是导致问题的嵌套循环,因为如果我尝试这个也无法匹配:

foreach (@chk)
{
        @final = (grep /^$_/, @new1);
}

@final是空的,但我知道$ _的至少88个entires在@ new1。

我在运行Windows ActivePerl 5.14.2的计算机上编写了此代码,顶级代码正常工作。然后我(使用@ new1的副本)比较两者并删除任何重复项(也适用于5.14.2)。我确实试图否定if匹配,但这似乎消灭了@ new1数组(因此我不需要进行哈希比较)。

当我尝试在带有Perl 5.8.0的Linux RedHat盒子上运行此代码时,它似乎很难与REGEX中的变量匹配。如果我用一个例子硬编码REGEX,我知道在@ new1中匹配有效,在第一个代码中删除了条目(在第二个值中插入了@final)。

@chk数组是Web服务器上的列表文件,通过在Web服务器上打开两个日志文件然后将一个文件推送到另一个日志文件来创建@ new1数组。

我甚至遇到了在每次循环迭代中打印$ test和$ check并手动检查以查看是否有任何值匹配且其中一些值有效的问题。

这让我困惑了几天,我不得不放弃并寻求帮助,任何想法?

3 个答案:

答案 0 :(得分:1)

使用\Q不知道您的输入数据是什么样的,可能会有所帮助:

if ($test =~ /^\Q$check/i);

请参阅quotemeta

答案 1 :(得分:1)

目前尚不清楚你要做什么。但是,您可能只是尝试获取那些不匹配的元素,反之亦然。根据您的需要调整以下代码

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

my @item  = qw(...); # your @new?
my @check = qw(...); # your @chk?
my @match;
my @nomatch;

ITEM:
foreach my $item (@item) {

   CHECK:
   foreach my $check (@check) {
      # uncomment this if $check should not be interpreted as a pattern,
      # but as literal characters:
      # $item = '\Q' . $item;
      if ($item =~ /^$check/) {
         push @match, $item;
         next ITEM; # there was a match, so this $item is burnt
          # we don't need to test against other $checks.
      }
   }

   # there was no match, so lets store it:
   push @nomatch, $item.
}

print "matched $_\n" for @matched;
print "didn't match $_" for @nomatch;

您的代码有点难以阅读。我告诉你这是什么

foreach (@chk) {
   @final = (grep /^$_/, @new1);
}

确实:它大致相当于

my @final = ();
foreach my $check (@chk) {
   @final = grep /^$check/, @new1;
}

相当于

my @final = ();
foreach my $check (@chk) {
   # @final = grep /^$check/, @new1;
   @final = ();
   foreach (@new) {
      if (/^$check/) {
         push @final, $_;
         last;
      }
   }
}

所以@final数组会被重置,可能会被清空。

答案 2 :(得分:1)

经用户1568538测试,解决方案是替换

chomp $check;

$check =~ s/\r\n//g;

从变量中删除Windows样式的行结尾。


由于chomp从其参数的末尾删除了输入记录分隔符$/的内容,因此您还可以更改其值:

my $pointer = 0;
foreach (@new1)
{
   my $test = $_;
   foreach (@chk)
   {
       local $/="\r\n";
       my $check = $_;
       chomp $check;
       delete($new1[$pointer]) if ($test =~ /^$_/i);
   }
   $pointer++;
}

但是,由于$/也会影响其他操作(例如从文件句柄中读取),因此除非您确定它是否安全,否则最安全的做法是避免更改$/。在这里,我将更改限制为发生foreach的{​​{1}}循环。