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

的不匹配變量if語句永遠不匹配的事實@名new1陣列中的許多條目確實包含$檢查在數組(88至少)的開始。 我不知道它是嵌套循環,導致該問題的原因是,如果我嘗試這一點,也無法匹配:Perl的IF語句正則表達式

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

@final是空的,但我知道至少有88個entires爲$ _是@名new1。

我在運行Windows ActivePerl 5.14.2的機器上編寫了這段代碼,並且最上面的代碼有效。然後,我(使用@ new1的副本)比較兩者並刪除任何重複項(也適用於5.14.2)。我確實試圖否定if匹配,但似乎消滅了@ new1數組(所以我不需要做一個哈希比較)。

當我嘗試在Linux RedHat框中使用Perl 5.8.0運行此代碼時,它似乎很難與REGEX中的變量匹配。如果我用一個我知道在@ new1中的例子對REGEX進行硬編碼,匹配將起作用,並且在第一個代碼中該條目將被刪除(在第二個值中插入@final)。

@chk數組是Web服務器上的列表文件,通過在Web服務器上打開兩個日誌文件,然後將其中一個推入另一個文件,創建@ new1數組。

我甚至花費了在每個循環迭代中打印出$ test和$ check的麻煩,並且手動檢查是否有任何值匹配,其中一些值是否匹配。

它讓我感到困惑好幾天了,我不得不扔掉毛巾尋求幫助,有什麼想法?

+2

顯示'@ new1'和'@ chk'的一些內容。 – toolic 2012-08-01 13:01:30

+2

我注意到你在'@ chk'的值上使用'chomp',而不是'@ new1'的值,並且你最初在Windows上開發了這個代碼。這兩個列表最初是如何填充的?如果'@ chk'中的字符串具有Windows行結束符,那麼Linux下的'chomp'將只刪除'\ n',而不是'\ r \ n'。對陣列的 – chepner 2012-08-01 13:07:37

+2

[delete](http://p3rl.org/delete)已棄用。如果你想刪除一個元素,使用[splice](http://p3rl.org/splice)。如果你想取消定義一個元素,使用[undef](http://p3rl.org/undef)。 – daxim 2012-08-01 13:11:28

回答

1

如user1568538,測得該溶液與

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

取代

chomp $check; 

從可變除去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++; 
} 

然而,由於$/還影響其它操作(如從文件句柄讀取),也許最安全的做法是避免更改$/,除非您確定它是否安全。在這裏,我將限制更改爲出現chompforeach循環。

+1

你仍然在使用數組上的'delete'。而且你仍然在改變自己的陣列。 *¡沒有我gusta,señor!* – tchrist 2012-08-02 13:21:21

+0

您正確地使用'$ _'修改數組。但是,我將爲此答案留下'delete'。最初的問題是關於正則表達式匹配失敗,並且已經修復。由於'delete'與'slice'或'undef'語義略有不同('slice'總是縮小數組,'undef'永遠不會,'delete'只會在最後一項被刪除時才縮小數組),I認爲確定正確的替代方案超出了這個問題的範圍。 – chepner 2012-08-02 13:50:55

1

不知道您的輸入數據是什麼樣子,使用\Q可能幫助:

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

quotemeta

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陣列被複位,可能是空的。

+0

該代碼的作品,這是一個簡單的小學生錯誤使用chomp周圍的錯誤。 – Chris 2012-08-02 12:59:40