在 Perl 程式中我們常會需要比較某個字串是否合於某個樣式, 以便決定是否對這個字串資料作進一步的處理, 這裡的樣式就是所謂的正規表示式
一個簡單的例子
if ( $str =~ /abc/ ) { print $str;}
上面這個例子是說如果 $str 比對符合有 abc 這個字串, 就將 $str 印出來
1. =~ 代表的是比對符合
2. !~ 可以用來表示比對不符合的情形
3. 如果要 case insensitive 比對, 用 /abc/i 代替 /abc/ 即可
4. / 代表比對邊界的開始與結束
5. 如果要比對的字串中含有 / 字元, 以 $str 是否比對符合有 "/home" 字串為例, 比對敘述可以有下面兩種處理方式
a. $str =~ /\/home/
將 / 字元前面加一反斜線 \, 讓字串中的 / 字元不具有比對邊界字元的意思
b. $str =~ m!/home!
透過 m 命令將邊界字元換成其它字元, 在這裡我們將邊界字元換成 !
更精簡的例子 ( 利用 $_)
if ( /abc/ ) { print;}
這個更短的例子看起來有點怪, 其實是因為它隱藏了 $_ 這個內定運算元, 當 Perl 中你看不到運算元時, 表示此時運算元是內定運算元 $_, 上面這個例子其實就是
if ( $_=~/abc/ ) { print $_;}
Character Pattern
表示法 | 意義 |
任意字母 | 代表此字母本身 |
. | 代表除換行字元外的任意一個字元 |
[任意個任意字元] | 代表一個在 [] 中出現的字元 |
[^任意個任意字元] | 代表一個不在 [] 中出現的字元 |
範例
/abcd/任意含 abcd 的字串
/a.b/a 帶一個任意字元, 後面接著一個 b
/[abc]xy/a 或 b 或 c 其後帶著 xy
/[^abc]xy/abc 以外任一字元帶著 xy
Buildin Character Class
表示法 | 意義 |
\d | [0-9] |
\D | [^0-9] |
\w | [A-Za-z] |
\W | [^A-Za-z] |
\s | [ \r\t\n\f] |
\S | [^ \r\t\n\f] |
範例
/[\dA-Fa-f]/16 進位數字 0..9a..f
Multipler
表示法 | 意義 |
* | 代表 * 前一個字元出現 0 到任意多次 |
+ | 代表 + 前一個字元出現 1 到任意多次 |
? | 代表 ? 前一個字元出現 0 或 1 次 |
{repeat} | 代表 { } 之前的字元出現 repeat 次 |
範例
/ab+c/a 跟著一個以上的b, 再跟著 c, 比如 abc, abbc, abbbc, abbbbc, abbbbbc, abbbbbc.....
/ab{5}c/a 跟著 5 個 b, 再跟著 c,
Anchor Pattern (定位樣式)
表示法 | 意義 |
^ | 字首 |
$ | 字尾 |
\b | word boundary |
\B | not word boundary |
範例
/^a.*c$/a 開頭 c 結尾的任意字串
/\bFred\B/與 Frederich 符合, 但與 Fred liu 不符合
利用 ( ) 記憶比對結果
當 pattern 中有 ( ) 時, ( ) 中的部份在比對成功時會依序被記錄到 $1, $2, $3.... 這些個變數中,
在 pattern 的其它部份可以分別用 \1, \2, \3... 來引用 $1, $2, $3 的內容
範例
/(b*)a\1/代表 a, bab, bbabb, bbbabbb, bbbbabbbb .....
當 pattern 中有 ( ) 時, 比對成功後, 記錄在 $1, $2, $3... 的內容可以被程式的其它部份使用
範例
if ( m!\s(\w+)://([\w\d#~%&+:\-\.])/?(.*)\s! ) { $protocol=$1; $host=$2; $path=$3;}
代換運算
正規表示式除了用來作比對外, 也可以用來做字串代換
表示法 | 意義 |
s/原字串 pattern/新字串/ | 字串代換(至多一次) |
s/原字串 pattern/新字串/g | 字串代換(全部代換) |
s!原字串 pattern!新字串! | 字串代換, 改以 ! 為分隔字元 |
範例
s/alpha/beta/將 alpha 換成 beta
s/alpha/beta/g將所有的 alpha 換成 beta
. 代表任意字元,但不包括換行字元 \n
* 代表比對成功的次數是 0 或 0 次以上
+ 代表比對成功的次數是 1 或 1 次以上
? 代表比對成功的次數是 0 或 1 次 (若用在其它數量修飾子之後,則表示 "比對採不貪心的模式")
^ 代表字串開頭
$ 代表字串結尾
\ 將其後的字元跳脫,使其回歸原字元的涵義,如:\\ , \. , \@ , \? , \*
| 樣式中的 或
( ) 群集
[0-9] 一個數字字元
[^0-9] 非數字
[a-z] 一個英文小寫字母
[^a-z] 非小寫
[A-Z] 一個英文大寫字母
[^A-Z] 非大寫
[a-zA-Z] 英文字母
[^a-zA-Z] 非英文字母
\d 同 [0-9] 數字
\D 同 [^0-9] 非數字
\w 文字, 同 [a-zA-Z0-9_]
\W 非文字,同 [^a-zA-Z0-9_]
\s 空白字元,同 [ \t\n\r\f]
\S 非空白字元,同 [^ \t\n\r\f]
\b 單字的邊界
\B 非單字的邊界
\xnn 16 進位數 nn
\nnn 8 進位數 nnn
{n} 剛好 n 次
{n, } n 次以上
{n, m} 至少 n 次,但不能超過 m 次
更多關於 Regular Expression 的說明
請看這裡
以下是相對的一些例子。記住它們皆須被置於 /.../中來使用。
t.e # t 後面跟隨著的任何字元其後跟隨的是 e
# This will match the
# tre
# tle
# but not te
# tale
^f # f 在一行的起始
^ftp # ftp 在一行的起始
e$ # e 在一行的尾端
tle$ # tle 在一行的尾端
und* # un 之後跟髓著零或多個 d 字元
# This will match un
# und
# undd
# unddd (etc)
.* # 任何一個沒有 newline 的字串。這是因為 . 吻合任何字串除了 newline 並且 * 代表零或多個這種情況
^$ # 空無一物的一行
以下是更多其它的選擇。中括弧被用來比對括弧中的任何一個字元,而括弧中的
- 代表 "介於",並且開始的
^ 代表 "無":
[qjk] # q 或 j 或 k 任何一者
[^qjk] # 非 q 或 j 或 k 任何一者
[a-z] # 任何介於 a 到 z 者
[^a-z] # 無小寫字母
[a-zA-Z] # 任何英文字母
[a-z]+ # 任何非零的小寫字元
到此你(妳)或許可以跳到最後的練習部分,剩下的部分僅供參考。一個垂值的
| 表示 "or" ,並且
(...
) 能用來做聚合的作用:
jelly|cream # jelly 或 cream 兩者之一
(eg|le)gs # eggs 或 legs 兩者之一
(da)+ # da 或 dada 或 dadada 或...
Here are some more special characters:
\n # A newline
\t # A tab
\w # Any alphanumeric (word) character.
# The same as [a-zA-Z0-9_]
\W # Any non-word character.
# The same as [^a-zA-Z0-9_]
\d # Any digit. The same as [0-9]
\D # Any non-digit. The same as [^0-9]
\s # Any whitespace character: space,
# tab, newline, etc
\S # Any non-whitespace character
\b # A word boundary, outside [] only
\B # No word boundary
Clearly characters like
$,
|,
[,
),
\,
/
and so on are peculiar cases in regular expressions. If you want to
match for one of those then you have to preceed it by a backslash.
So:
\| # Vertical bar
\[ # An open square bracket
\) # A closing parenthesis
\* # An asterisk
\^ # A carat symbol
\/ # A slash
\\ # A backslash
and so on.
As
was mentioned earlier, it's probably best to build up your use of
regular expressions slowly. Here are a few examples. Remember that
to use them for matching they should be put in
/...
/ slashes
[01] # Either "0" or "1"
\/0 # A division by zero: "/0"
\/ 0 # A division by zero with a space: "/ 0"
\/\s0 # A division by zero with a whitespace:
# "/ 0" where the space may be a tab etc.
\/ *0 # A division by zero with possibly some
# spaces: "/0" or "/ 0" or "/ 0" etc.
\/\s*0 # A division by zero with possibly some
# whitespace.
\/\s*0\.0* # As the previous one, but with decimal
# point and maybe some 0s after it. Accepts
# "/0." and "/0.0" and "/0.00" etc and
# "/ 0." and "/ 0.0" and "/ 0.00" etc.