- Perl 基礎
- Perl - 首頁
- Perl - 簡介
- Perl - 環境
- Perl - 語法概述
- Perl - 資料型別
- Perl - 變數
- Perl - 標量
- Perl - 陣列
- Perl - 雜湊
- Perl - IF...ELSE
- Perl - 迴圈
- Perl - 運算子
- Perl - 日期和時間
- Perl - 子程式
- Perl - 引用
- Perl - 格式
- Perl - 檔案 I/O
- Perl - 目錄
- Perl - 錯誤處理
- Perl - 特殊變數
- Perl - 編碼規範
- Perl - 正則表示式
- Perl - 傳送郵件
- Perl 高階
- Perl - 套接字程式設計
- Perl - 面向物件
- Perl - 資料庫訪問
- Perl - CGI 程式設計
- Perl - 包和模組
- Perl - 程序管理
- Perl - 嵌入式文件
- Perl - 函式引用
- Perl 有用資源
- Perl - 問答
- Perl - 快速指南
- Perl - 有用資源
- Perl - 討論
Perl - 正則表示式
正則表示式是一串字元,用於定義您正在檢視的模式或模式。Perl 中正則表示式的語法與您在其他支援正則表示式的程式(如sed、grep和awk)中找到的非常相似。
應用正則表示式的基本方法是使用模式繫結運算子 =~ 和!~。第一個運算子是測試和賦值運算子。
Perl 中有三個正則表示式運算子。
- 匹配正則表示式 - m//
- 替換正則表示式 - s///
- 轉錄正則表示式 - tr///
在每種情況下,正斜槓都充當您指定的正則表示式 (regex) 的分隔符。如果您習慣使用任何其他分隔符,則可以使用它代替正斜槓。
匹配運算子
匹配運算子 m// 用於將字串或語句與正則表示式匹配。例如,要將字元序列“foo”與標量 $bar 匹配,您可以使用以下語句:
#!/usr/bin/perl
$bar = "This is foo and again foo";
if ($bar =~ /foo/) {
print "First time is matching\n";
} else {
print "First time is not matching\n";
}
$bar = "foo";
if ($bar =~ /foo/) {
print "Second time is matching\n";
} else {
print "Second time is not matching\n";
}
執行上述程式時,會產生以下結果:
First time is matching Second time is matching
m// 實際上以與 q// 運算子系列相同的方式工作。您可以使用任何自然匹配字元的組合來充當表示式的分隔符。例如,m{}、m() 和 m>< 都是有效的。因此,上述示例可以改寫如下:
#!/usr/bin/perl
$bar = "This is foo and again foo";
if ($bar =~ m[foo]) {
print "First time is matching\n";
} else {
print "First time is not matching\n";
}
$bar = "foo";
if ($bar =~ m{foo}) {
print "Second time is matching\n";
} else {
print "Second time is not matching\n";
}
如果分隔符是正斜槓,則可以省略 m,但對於所有其他分隔符,您必須使用 m 字首。
請注意,整個匹配表示式(即 =~ 或 !~ 左側的表示式和匹配運算子)如果表示式匹配,則在標量上下文中返回 true。因此,語句:
$true = ($foo =~ m/foo/);
如果 $foo 與正則表示式匹配,則將 $true 設定為 1,否則如果匹配失敗則設定為 0。在列表上下文中,匹配返回任何分組表示式的內容。例如,在從時間字串中提取小時、分鐘和秒時,我們可以使用:
my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
匹配運算子修飾符
匹配運算子支援自己的修飾符集。/g 修飾符允許全域性匹配。/i 修飾符將使匹配不區分大小寫。以下是修飾符的完整列表
| 序號 | 修飾符和描述 |
|---|---|
| 1 | i 使匹配不區分大小寫。 |
| 2 | m 指定如果字串具有換行符或回車符,則 ^ 和 $ 運算子將匹配換行符邊界,而不是字串邊界。 |
| 3 | o 僅評估表示式一次。 |
| 4 | s 允許使用 . 匹配換行符。 |
| 5 | x 允許您在表示式中使用空格以提高畫質晰度。 |
| 6 | g 全域性查詢所有匹配項。 |
| 7 | cg 允許搜尋即使在全域性匹配失敗後繼續。 |
僅匹配一次
匹配運算子還有一個更簡單的版本 - ?PATTERN? 運算子。這基本上與 m// 運算子相同,只是它在每次重置之間的每次呼叫中只匹配字串中的一次。
例如,您可以使用它來獲取列表中的第一個和最後一個元素:
#!/usr/bin/perl
@list = qw/food foosball subeo footnote terfoot canic footbrdige/;
foreach (@list) {
$first = $1 if /(foo.*?)/;
$last = $1 if /(foo.*)/;
}
print "First: $first, Last: $last\n";
執行上述程式時,會產生以下結果:
First: foo, Last: footbrdige
正則表示式變數
正則表示式變數包括$,它包含上次分組匹配匹配的內容;$&,它包含整個匹配字串;$`,它包含匹配字串之前的所有內容;以及$',它包含匹配字串之後的所有內容。以下程式碼演示了結果:
#!/usr/bin/perl $string = "The food is in the salad bar"; $string =~ m/foo/; print "Before: $`\n"; print "Matched: $&\n"; print "After: $'\n";
執行上述程式時,會產生以下結果:
Before: The Matched: foo After: d is in the salad bar
替換運算子
替換運算子 s/// 實際上只是匹配運算子的擴充套件,它允許您將匹配的文字替換為一些新文字。運算子的基本形式為:
s/PATTERN/REPLACEMENT/;
PATTERN 是我們要查詢的文字的正則表示式。REPLACEMENT 是我們要用來替換找到的文字的文字或正則表示式的規範。例如,我們可以使用以下正則表示式將所有出現的dog替換為cat:
#/user/bin/perl $string = "The cat sat on the mat"; $string =~ s/cat/dog/; print "$string\n";
執行上述程式時,會產生以下結果:
The dog sat on the mat
替換運算子修飾符
以下是與替換運算子一起使用的所有修飾符的列表。
| 序號 | 修飾符和描述 |
|---|---|
| 1 | i 使匹配不區分大小寫。 |
| 2 | m 指定如果字串具有換行符或回車符,則 ^ 和 $ 運算子將匹配換行符邊界,而不是字串邊界。 |
| 3 | o 僅評估表示式一次。 |
| 4 | s 允許使用 . 匹配換行符。 |
| 5 | x 允許您在表示式中使用空格以提高畫質晰度。 |
| 6 | g 將所有找到的表示式的出現替換為替換文字。 |
| 7 | e 將替換評估為 Perl 語句,並將其返回值用作替換文字。 |
轉換運算子
轉換類似於但並不完全相同於替換的原理,但與替換不同,轉換(或轉錄)不使用正則表示式進行其搜尋和替換值。轉換運算子為:
tr/SEARCHLIST/REPLACEMENTLIST/cds y/SEARCHLIST/REPLACEMENTLIST/cds
轉換將 SEARCHLIST 中所有出現的字元替換為 REPLACEMENTLIST 中相應的字元。例如,使用我們在本章中一直在使用的“The cat sat on the mat.” 字串:
#/user/bin/perl $string = 'The cat sat on the mat'; $string =~ tr/a/o/; print "$string\n";
執行上述程式時,會產生以下結果:
The cot sot on the mot.
也可以使用標準的 Perl 範圍,允許您透過字母或數值指定字元範圍。要更改字串的大小寫,您可以使用以下語法代替uc函式。
$string =~ tr/a-z/A-Z/;
轉換運算子修飾符
以下是與轉換相關的運算子列表。
| 序號 | 修飾符和描述 |
|---|---|
| 1 | c 補充 SEARCHLIST。 |
| 2 | d 刪除找到但未替換的字元。 |
| 3 | s 壓縮重複替換的字元。 |
/d 修飾符刪除與 SEARCHLIST 匹配但 REPLACEMENTLIST 中沒有相應條目的字元。例如:
#!/usr/bin/perl $string = 'the cat sat on the mat.'; $string =~ tr/a-z/b/d; print "$string\n";
執行上述程式時,會產生以下結果:
b b b.
最後一個修飾符 /s 刪除了被替換的字元的重複序列,因此:
#!/usr/bin/perl $string = 'food'; $string = 'food'; $string =~ tr/a-z/a-z/s; print "$string\n";
執行上述程式時,會產生以下結果:
fod
更復雜的正則表示式
您不僅可以匹配固定字串。實際上,您可以使用更復雜的正則表示式匹配幾乎任何您能想到的東西。這是一個快速備忘單:
下表列出了 Python 中可用的正則表示式語法。
| 序號 | 模式和描述 |
|---|---|
| 1 | ^ 匹配行首。 |
| 2 | $ 匹配行尾。 |
| 3 | . 匹配除換行符之外的任何單個字元。使用 m 選項允許它匹配換行符。 |
| 4 | [...] 匹配括號中的任何單個字元。 |
| 5 | [^...] 匹配括號中不存在的任何單個字元。 |
| 6 | * 匹配前一個表示式的 0 次或多次出現。 |
| 7 | + 匹配前一個表示式的 1 次或多次出現。 |
| 8 | ? 匹配前一個表示式的 0 次或 1 次出現。 |
| 9 | { n} 匹配前一個表示式的正好 n 次出現。 |
| 10 | { n,} 匹配前一個表示式的 n 次或多次出現。 |
| 11 | { n, m} 匹配前一個表示式的至少 n 次且至多 m 次出現。 |
| 12 | a| b 匹配 a 或 b。 |
| 13 | \w 匹配單詞字元。 |
| 14 | \W 匹配非單詞字元。 |
| 15 | \s 匹配空格。相當於 [\t\n\r\f]。 |
| 16 | \S 匹配非空格。 |
| 17 | \d 匹配數字。相當於 [0-9]。 |
| 18 | \D 匹配非數字。 |
| 19 | \A 匹配字串開頭。 |
| 20 | \Z 匹配字串結尾。如果存在換行符,則匹配換行符之前。 |
| 21 | \z 匹配字串結尾。 |
| 22 | \G 匹配上次匹配完成的位置。 |
| 23 | \b 在括號外匹配單詞邊界。在括號內匹配退格鍵 (0x08)。 |
| 24 | \B 匹配非單詞邊界。 |
| 25 | \n, \t, 等。 匹配換行符、回車符、製表符等。 |
| 26 | \1...\9 匹配第 n 個分組子表示式。 |
| 27 | \10 如果第 n 個分組子表示式已匹配,則匹配它。否則引用字元程式碼的八進位制表示形式。 |
| 28 | [aeiou] 匹配給定集合中的單個字元 |
| 29 | [^aeiou] 匹配給定集合之外的單個字元 |
^ 元字元匹配字串的開頭,而 $ 元字元匹配字串的結尾。以下是一些簡短的示例。
# nothing in the string (start and end are adjacent)
/^$/
# a three digits, each followed by a whitespace
# character (eg "3 4 5 ")
/(\d\s) {3}/
# matches a string in which every
# odd-numbered letter is a (eg "abacadaf")
/(a.)+/
# string starts with one or more digits
/^\d+/
# string that ends with one or more digits
/\d+$/
讓我們看另一個例子。
#!/usr/bin/perl $string = "Cats go Catatonic\nWhen given Catnip"; ($start) = ($string =~ /\A(.*?) /); @lines = $string =~ /^(.*?) /gm; print "First word: $start\n","Line starts: @lines\n";
執行上述程式時,會產生以下結果:
First word: Cats Line starts: Cats When
匹配邊界
\b 在任何單詞邊界處匹配,由 \w 類和 \W 類之間的差異定義。因為 \w 包括單詞的字元,而 \W 包括相反的字元,所以這通常意味著單詞的終止。\B 斷言匹配任何不是單詞邊界的位置。例如:
/\bcat\b/ # Matches 'the cat sat' but not 'cat on the mat' /\Bcat\B/ # Matches 'verification' but not 'the cat on the mat' /\bcat\B/ # Matches 'catatonic' but not 'polecat' /\Bcat\b/ # Matches 'polecat' but not 'catatonic'
選擇備選方案
| 字元就像 Perl 中的標準或按位 OR。它在正則表示式或組中指定備選匹配。例如,要在表示式中匹配“cat”或“dog”,您可以使用:
if ($string =~ /cat|dog/)
您可以將表示式的各個元素組合在一起以支援複雜的匹配。搜尋兩個人的姓名可以透過兩個單獨的測試來實現,如下所示:
if (($string =~ /Martin Brown/) || ($string =~ /Sharon Brown/)) This could be written as follows if ($string =~ /(Martin|Sharon) Brown/)
分組匹配
從正則表示式的角度來看,兩者之間沒有區別,也許除了前者稍微更清晰之外。
$string =~ /(\S+)\s+(\S+)/; and $string =~ /\S+\s+\S+/;
但是,分組的好處是它允許我們從正則表示式中提取序列。分組按其在原始表示式中出現的順序返回為列表。例如,在以下片段中,我們從字串中提取了小時、分鐘和秒。
my ($hours, $minutes, $seconds) = ($time =~ m/(\d+):(\d+):(\d+)/);
除了這種直接方法之外,匹配的組也存在於特殊的 $x 變數中,其中 x 是正則表示式中組的編號。因此,我們可以將前面的示例改寫如下:
#!/usr/bin/perl $time = "12:05:30"; $time =~ m/(\d+):(\d+):(\d+)/; my ($hours, $minutes, $seconds) = ($1, $2, $3); print "Hours : $hours, Minutes: $minutes, Second: $seconds\n";
執行上述程式時,會產生以下結果:
Hours : 12, Minutes: 05, Second: 30
當組用於替換表示式時,$x 語法可以在替換文字中使用。因此,我們可以使用以下方法重新格式化日期字串:
#!/usr/bin/perl $date = '03/26/1999'; $date =~ s#(\d+)/(\d+)/(\d+)#$3/$1/$2#; print "$date\n";
執行上述程式時,會產生以下結果:
1999/03/26
\G 斷言
\G 斷言允許您從上次匹配發生的位置繼續搜尋。例如,在以下程式碼中,我們使用了 \G,以便我們可以搜尋到正確的位置,然後提取一些資訊,而無需建立更復雜、單個的正則表示式:
#!/usr/bin/perl
$string = "The time is: 12:31:02 on 4/12/00";
$string =~ /:\s+/g;
($time) = ($string =~ /\G(\d+:\d+:\d+)/);
$string =~ /.+\s+/g;
($date) = ($string =~ m{\G(\d+/\d+/\d+)});
print "Time: $time, Date: $date\n";
執行上述程式時,會產生以下結果:
Time: 12:31:02, Date: 4/12/00
\G 斷言實際上只是 pos 函式的元字元等效項,因此在正則表示式呼叫之間,您可以繼續使用 pos,甚至可以透過將 pos 用作 lvalue 子程式來修改 pos 的值(以及 \G)。
正則表示式示例
文字字元
| 序號 | 示例和描述 |
|---|---|
| 1 | Perl 匹配“Perl”。 |
字元類
| 序號 | 示例和描述 |
|---|---|
| 1 | [Pp]ython 匹配“Python”或“python” |
| 2 | rub[ye] 匹配 "ruby" 或 "rube" |
| 3 | [aeiou] 匹配任何一個小寫母音 |
| 4 | [0-9] 匹配任何數字;等同於 [0123456789] |
| 5 | [a-z] 匹配任何小寫 ASCII 字母 |
| 6 | [A-Z] 匹配任何大寫 ASCII 字母 |
| 7 | [a-zA-Z0-9] 匹配以上任何一個 |
| 8 | [^aeiou] 匹配除了小寫母音之外的任何字元 |
| 9 | [^0-9] 匹配除了數字之外的任何字元 |
特殊字元類
| 序號 | 示例和描述 |
|---|---|
| 1 | . 匹配除了換行符之外的任何字元 |
| 2 | \d 匹配一個數字: [0-9] |
| 3 | \D 匹配一個非數字: [^0-9] |
| 4 | \s 匹配一個空白字元: [ \t\r\n\f] |
| 5 | \S 匹配非空白字元: [^ \t\r\n\f] |
| 6 | \w 匹配單個單詞字元: [A-Za-z0-9_] |
| 7 | \W 匹配非單詞字元: [^A-Za-z0-9_] |
重複情況
| 序號 | 示例和描述 |
|---|---|
| 1 | ruby? 匹配 "rub" 或 "ruby": y 是可選的 |
| 2 | ruby* 匹配 "rub" 加 0 個或多個 y |
| 3 | ruby+ 匹配 "rub" 加 1 個或多個 y |
| 4 | \d{3} 精確匹配 3 個數字 |
| 5 | \d{3,} 匹配 3 個或更多個數字 |
| 6. | \d{3,5} 匹配 3、4 或 5 個數字 |
非貪婪重複
這將匹配最少的重複次數 -
| 序號 | 示例和描述 |
|---|---|
| 1 | <.*> 貪婪重複:匹配 "<python>perl>" |
| 2 | <.*?> 非貪婪:在 "<python>perl>" 中匹配 "<python>" |
使用括號進行分組
| 序號 | 示例和描述 |
|---|---|
| 1 | \D\d+ 無分組:+ 重複 \d |
| 2 | (\D\d)+ 分組:+ 重複 \D\d 對 |
| 3 | ([Pp]ython(, )?)+ 匹配 "Python"、"Python, python, python" 等。 |
反向引用
這將再次匹配先前匹配的組 -
| 序號 | 示例和描述 |
|---|---|
| 1 | ([Pp])ython&\1ails 匹配 python&pails 或 Python&Pails |
| 2 | (['"])[^\1]*\1 單引號或雙引號字串。\1 匹配第一個組匹配到的任何內容。\2 匹配第二個組匹配到的任何內容,依此類推。 |
備選方案
| 序號 | 示例和描述 |
|---|---|
| 1 | python|perl 匹配 "python" 或 "perl" |
| 2 | rub(y|le)) 匹配 "ruby" 或 "ruble" |
| 3 | Python(!+|\?) "Python" 後跟一個或多個 ! 或一個 ? |
錨點
這需要指定匹配位置。
| 序號 | 示例和描述 |
|---|---|
| 1 | ^Python 匹配字串或內部行開頭的 "Python" |
| 2 | Python$ 匹配字串或行結尾的 "Python" |
| 3 | \APython 匹配字串開頭的 "Python" |
| 4 | Python\Z 匹配字串結尾的 "Python" |
| 5 | \bPython\b 匹配單詞邊界處的 "Python" |
| 6 | \brub\B \B 是非單詞邊界:在 "rube" 和 "ruby" 中匹配 "rub",但不能單獨匹配 |
| 7 | Python(?=!) 匹配 "Python",如果後面跟著一個感嘆號 |
| 8 | Python(?!!) 匹配 "Python",如果後面不跟著感嘆號 |
帶括號的特殊語法
| 序號 | 示例和描述 |
|---|---|
| 1 | R(?#comment) 匹配 "R"。其餘部分是註釋 |
| 2 | R(?i)uby 在匹配 "uby" 時不區分大小寫 |
| 3 | R(?i:uby) 與上面相同 |
| 4 | rub(?:y|le)) 僅分組,不建立 \1 反向引用 |