2013-11-14 46 views
1

我試圖匹配來自Perl程序中某個文件的某些數據模式。由於比賽可能在多條線上,因此我將線分隔符定義爲未定義。Perl正則表達式意外地似乎在修改源字符串

$/ = undef ; 

現在,由於匹配可以跨越多行並且多於一行,因此我使用smgi修飾符。

if ($msgText =~ /$msgTypeExpr/smgi) 

現在,我遇到的問題是上面的變量$ msgText被修改,雖然我沒有取代它。

下面是相關代碼:

open (HANDLE1,"$file") || die "cannot open file \n"; 
$/ = undef ; 
while (my $msgText = <HANDLE1>) 
{ 
     my $msgTypeExpr = "<city\\W+"; 

     print "Attempt 1:\n"; 
     if ($msgText =~ /$msgTypeExpr/smgi) 
     { 
       print "matched\n"; 
     } 
     else 
     { 
       print " not matched \n"; 
     } 

     print "Attempt 2:\n"; 
     if ($msgText =~ /$msgTypeExpr/smgi) 
     { 
       print "matched\n"; 
     } 
     else 
     { 
       print " not matched \n"; 
     } 
} 

測試輸入文件看起來是這樣的:

<city 
name="abc"> 
</city> 

人們期望匹配模式的兩倍,但它只是不匹配的第一次第二次。

我已經臨時解決了這個問題,現在在匹配和使用該臨時變量進行匹配之前先指定一個臨時變量。

my $tmpMsgText = $msgText ; 

這是我第一次在這個論壇上發帖提問,所以請原諒所有禮儀我可能犯了錯,也請善待足以指出來,這樣我就不會在重複未來。

+2

如果文件是一個XML文件,你應該用XML解析器解析它,而不要試圖用正則表達式來完成。 –

+0

raina77ow - 他正在執行2倍的同樣的事情,所以我相信他希望在兩個時代都匹配<城市。但是由於/ g開關,他的代碼中沒有發生 – Davs

回答

2

if (//g)是沒有意義的。 「如果匹配,並繼續匹配,直到沒有匹配」?擺脫g

我不知道你爲什麼使用sm要麼。

s是無用的,因爲該模式不包含.

m是無用的,因爲該模式不包含^$


實際上,標量上下文中的//g充當迭代器。

$ perl -E'$_ = "abc"; /(.)/g && say $1; /(.)/g && say $1;' 
a 
b 
+0

謝謝@ikegami –

2

首先,我不確定讀這樣的文件。修改那些Perl的特殊變量,比如$ /應與當地完成,像這樣:

local $/ = undef; 

這樣的變量只在當前範圍內修改(從而避免可能的行動中,在距離錯誤) 。通過將$ /設置爲undef,您將一次讀取整個文件,因此在那裏放置一個while循環沒有意義。我想讀取整個文件是這樣的:

open my $fh, "<", "somefile" or die; 
my $content = do { local $/ = undef; <$fh> }; 

的DO塊限制修改$ /價值只體現在一個聲明(它會創建一個新的範圍)。

關於正則表達式匹配:在正則表達式之後移除/ g修飾符。如果我沒有記錯,它會記住最後一個正則表達式搜索位置並從那裏繼續。同樣爲了檢測字符串是否被更改,在這些匹配之前和之後打印變量。你會看到,他們沒有被修改。 相反的:

if ($msgText =~ /$msgTypeExpr/smgi) 

地說:

if ($msgText =~ /$msgTypeExpr/smi) 
+0

是的,你記得正確:在標量上下文中,對字符串的連續調用將從匹配跳轉到匹配。 – raina77ow

+0

謝謝@Davs。您的建議非常有幫助 –