2010-09-22 39 views
5

我正在編輯一個Perl文件,但我不明白這個正則表達式比較。有人可以向我解釋嗎?

if ($lines =~ m/(.*?):(.*?)$/g) { } .. 

這裏會發生什麼? $lines是來自文本文件的一行。

+0

貌似第一個'(。*?)'總是會匹配空字符串。 – 2010-09-22 16:40:00

+1

並非總是如此。它會匹配所有字符到第一個冒號。 – CanSpice 2010-09-22 16:43:44

回答

11

把它分解成幾部分:

$lines =~ m/ (.*?)  # Match any character (except newlines) 
         # zero or more times, not greedily, and 
         # stick the results in $1. 
      :   # Match a colon. 
      (.*?)  # Match any character (except newlines) 
         # zero or more times, not greedily, and 
         # stick the results in $2. 
      $   # Match the end of the line. 
      /gx; 

所以,這會匹配":"字符串(它可以匹配零個的字符,然後一個冒號,則該行年底前零個字符,$1$2是空的字符串)或"abc:"$1 = "abc",$2是空字符串)或"abc:def:ghi"$1 = "abc"$2 = "def:ghi")。

如果你傳入一個不匹配的行(看起來像這是字符串不包含冒號),那麼它將不處理括號內的代碼。但是,如果它匹配,那麼括號內的代碼就可以使用和處理特殊的變量(至少,直到下一個正則表達式出現,如果括號內有一個)。

1

(.*?)捕獲任何字符,但儘可能少的字符。

因此,它看起來像<something>:<somethingelse><end of line>模式,如果有多個:字符串中,第一個將用作<something><somethingelse>之間的分隔符。

2

該行表示執行正則表達式匹配$lines與正則表達式m/(.*?):(.*?)$/g。如果找不到匹配,可以在$linesfalse中找到匹配項,它將有效返回true

=~的操作的說明:

二進制 「=〜」 結合一個標量表達式 到一個模式匹配。某些操作 默認爲搜索或修改字符串$ _ 。該操作員使其他 字符串的操作可以在 上運行。正確的參數是搜索 模式,替代或 音譯。左邊的參數是 應該搜索什麼, 替代,或音譯代替 的默認$ _。當在標量 上下文中使用時,返回值通常爲 指示 操作的成功。

正則表達式本身是:

m/ #Perform a "match" operation 
(.*?) #Match zero or more repetitions of any characters, but match as few as possible (ungreedy) 
:  #Match a literal colon character 
(.*?) #Match zero or more repetitions of any characters, but match as few as possible (ungreedy) 
$  #Match the end of string 
/g #Perform the regex globally (find all occurrences in $line) 

因此,如果針對該正則表達式匹配$lines,它會進入有條件的部分,否則將false,將跳過它。

9

有一個工具可以幫助理解正則表達式:YAPE::Regex::Explain

忽略g修改,這裏沒有必要:

use strict; 
use warnings; 
use YAPE::Regex::Explain; 

my $re = qr/(.*?):(.*?)$/; 
print YAPE::Regex::Explain->new($re)->explain(); 

__END__ 

The regular expression: 

(?-imsx:(.*?):(.*?)$) 

matches as follows: 

NODE      EXPLANATION 
---------------------------------------------------------------------- 
(?-imsx:     group, but do not capture (case-sensitive) 
         (with^and $ matching normally) (with . not 
         matching \n) (matching whitespace and # 
         normally): 
---------------------------------------------------------------------- 
    (      group and capture to \1: 
---------------------------------------------------------------------- 
    .*?      any character except \n (0 or more times 
          (matching the least amount possible)) 
---------------------------------------------------------------------- 
)      end of \1 
---------------------------------------------------------------------- 
    :      ':' 
---------------------------------------------------------------------- 
    (      group and capture to \2: 
---------------------------------------------------------------------- 
    .*?      any character except \n (0 or more times 
          (matching the least amount possible)) 
---------------------------------------------------------------------- 
)      end of \2 
---------------------------------------------------------------------- 
    $      before an optional \n, and the end of the 
          string 
---------------------------------------------------------------------- 
)      end of grouping 
---------------------------------------------------------------------- 

perldoc perlre見。

+1

這該死的整潔! – 2010-09-22 18:37:19

3

這是由誰知道太多關於正則表達式或者不太瞭解$'$`變量的人寫的。

這可能是寫成

if ($lines =~ /:/) { 
    ... # use $` ($PREMATCH) instead of $1 
    ... # use $' ($POSTMATCH) instead of $2 
} 

if (($var1,$var2) = split /:/, $lines, 2 and defined($var2)) { 
    ... # use $var1, $var2 instead of $1,$2 
} 
+1

如果要使用/:/,請使用Perl 5.10中的/ p標誌和$ {^ PREMATCH}和$ {^ POSTMATCH}變量。不過,我寧願分手,因爲這就是實際發生的事情。 – 2010-09-22 20:16:53