標籤:
Regex
簡單模式:匹配$_中的內容,只需要將模式寫在一對斜線(/)中就可以了。
如:#!/usr/bin/env perl
use 5.010;
$_="yabba dabba doo";
if(/abba/){
say "it matched!";
}
關於元字元
和shell中的差不多:
.==>任一字元;
*==>重複0次及其0次以上;
+==>重複一次及一次以上;
?==>重複0次或一次;
模式分組
在Regex中,用圓括弧()對字串分組。
反向引用的寫法是在斜線後面接上數字編號,如\1 \2這樣。相應的數字表示對應順序的擷取的群組。
下面舉例說明:
反向引用也不必進接在對應的擷取的群組的後面。下面的模式或匹配y後面的4個連續的非分行符號,並用\1反向參考資料表示匹配d後也出現的4個字元的情況。
$_=”yabba dabba doo”;
If (/y(....) d\1/){
Print “It matched the same after y and d!\n”;
}
也可以用多個括弧來分成多組,每個組都可以有自己的反向引用。
$_=”yabba dabba doo”;
If (/y(.)(.)\2\1/){ #匹配 ‘abba’
Print “It matched the same after y and d!\n”;
}
那麼如何區分哪個括弧是第幾組呢?Larry給出的解釋:只要一次點算左括弧(包括嵌套括弧)的序號就OK了。如:
$_=”yabba dabba doo”;
if (/y((.)(.)\3\2) d\1/){
print “It matched the same after y and d!\n”;
}
拆開:( #第一個括弧
(.) #第二個括弧
(.) #第三個括弧
\3
\2
)
上面遺留的問題:
$_=”aa11bb”;
If (/(.)\111/){
print “It matched!\n”;
}
原本是打算匹配aa11 ,現在好了。Perl將其理解為匹配第111組括弧,根本找不到這個括弧,報錯。
解決方案:\g{1} 就可以消除反向引用與模式的直接量部分的二義性。
use 5.010;
$_=”aa11bb”;
If (/(.)\g{1}11/){
print “It matched.”.”\n”;
}
而且用\g{N}還有一個好處就是N可以是負數,也就是說可以為-1 -2等。表示的意思就是倒數或者說相對位置。
-1 表示離\g{-1}最近的第一個左括弧;
-2 表示離\g{-2}最近的第二個左括弧;
use 5.010;
$_=”aa11bb”;
if (/(.)(.)\g{-1}11/){
print “It matched.”.”\n”;
}
擇一匹配
(|)
如:/fred(and|or)barney/
字元集
[a-zA-Z]
[^a-zA-Z]
字元集的簡寫
表示任意一個數位字元集簡寫\d;
$_=’The HAL-9000 requires authorization to continue.’;
if (/HAL-[\d]+/){
say “It matched.”
}
修飾符/a,寫在Regex末尾,表示按照ASCII的語義展開(從Perl 5.14引入的修飾符):
use 5.014;
$_=’The HAL-9000 requires authorization to continue.’;
If (/HAL-[\d]+/a){ #俺老的ASCII字元解釋
say “It matched.”
}
說明:引入/a的主要原因是因為\d 現在的語義不僅再是[0-9]這個範圍了,它還表示了很多比較特殊的數字元。
\s能匹配以下5個空白字元:換頁符\f 水平定位字元\v 垂直定位字元\h 斷行符號符\n 空格符\p
use 5.014;
if (/\s/a){ #按老的ASCII字元語義解釋
say “The string matched ASCII whitescape”;
}
\R匹配斷行符,無論是\r\n還是\n都能匹配。
\w匹配“單詞”字元,所謂單詞其實是[a-zA-Z0-9]組成的。
反義簡寫
\D 表示[^\d]
\W 表示[^\w]
\S 表示[^\s]
這些簡寫既可以做為模式裡獨立的字元集,也可以作為方括弧裡字元集的一部分。比如:/[\dA-Fa-f]/
用Regex進行匹配用m//進行匹配
前面所講的用//寫法表示模式,比如/fred/事實上是m//的特例。
通用像qw //一樣,分隔字元也是可選的如:m{fred} m <fred>
模式修飾符
/a 表示按照ASCII的語義展開
/i 表示進行大小寫無關的匹配
print “would you like to play a game?”;
chomp($_=<STDIN>);
If(/yes/i){ #大小寫無關的匹配
say “i like too.”;
}
/s 表示匹配任一字元;
在很多情況下(.)是沒有辦法匹配到分行符號的,但如果字串中含有分行符號,而你有希望匹配這些分行符號,那麼就可以用/s修飾符完成。(實現原理是,Perl會將點號轉換成字元集[\d\D]來處理,就是說會匹配任一字元)
$_=”I saw Barney\n down at the bowling alley\nwith Fred\nlast night.\n”;
If (/Barney.*Fred/s){
Print “That string mentions Fred after Barney\n”;
}
出現的問題:/s會把模式中所出現的.都修改成能匹配任一字元,那如果我們只是想其中幾個匹配任一字元呢?可以用\N
/x 表示加入空白符;
舉例如下:
#!/usr/bin/env perl
use 5.010;
$_="fred";
if(/fre d/x){
say "it matched."
}
當然上面的修飾符都可以組合:
if(/barney.*fred/is){#同時使用/i和/s
print “That string mentions Fred after Barney!\n”;
}
perl學習筆記——Regex