複製鏈接
請複製以下鏈接發送給好友

正規表達式

鎖定
正規表達式由一個或多個字符型文字和/或元字符組成。在最簡單的格式下,正規表達式僅由字符文字組成,如正規表達式 cat。它被讀作字母 c,接着是字母 a 和 t,這種模式匹配 cat、location 和 catalog 之類的字符串。可以用它們驗證數據、識別重複關鍵字的出現、檢測不必要的空格、分析字符串、驗證電話號碼、郵政編碼電子郵件地址社會安全號碼、IP 地址、文件名路徑名等的格式,也可以查找如 HTML 標記、數字、日期之類的模式,或任意文本數據中符合任意模式的任何事物,並用其它的模式來替換它們。
中文名
正規表達式
組    成
一個或多個字符型文字和/或元字符

正規表達式定義及介紹

正規表達式由一個或多個字符型文字和/或元字符組成。在最簡單的格式下,正規表達式僅由字符文字組成,如正規表達式 cat。它被讀作字母 c,接着是字母 a 和 t,這種模式匹配 cat、location 和 catalog 之類的字符串。元字符提供算法來確定 Oracle 如何處理組成一個正規表達式的字符。當您瞭解了各種元字符的含義時,您將體會到正規表達式用於查找和替換特定的文本數據是非常強大的。
驗證數據、識別重複關鍵字的出現、檢測不必要的空格,或分析字符串只是正規表達式的許多應用中的一部分。您可以用它們來驗證電話號碼、郵政編碼、電子郵件地址社會安全號碼、IP 地址、文件名和路徑名等的格式。此外,您可以查找如 HTML 標記、數字、日期之類的模式,或任意文本數據中符合任意模式的任何事物,並用其它的模式來替換它們。

正規表達式基本介紹

您可以使用最新引進的 Oracle SQL REGEXP_LIKE 操作符和 REGEXP_INSTR、REGEXP_SUBSTR 以及 REGEXP_REPLACE 函數來發揮正規表達式的作用。您將體會到這個新的功能如何對 LIKE 操作符和 INSTR、SUBSTR 和 REPLACE 函數進行了補充。實際上,它們類似於已有的操作符,但現在增加了強大的模式匹配功能。被搜索的數據可以是簡單的字符串或是存儲在數據庫字符列中的大量文本。正規表達式讓您能夠以一種您以前從未想過的方式來搜索、替換和驗證數據,並提供高度的靈活性。

正規表達式基本例子

在使用這個新功能之前,您需要了解一些元字符的含義。句號 (.) 匹配一個正規表達式中的任意字符(除了換行符)。例如,正規表達式 a.b 匹配的字符串中首先包含字母 a,接着是其它任意單個字符(除了換行符),再接着是字母 b。字符串 axb、xaybx 和 abba 都與之匹配,因為在字符串中隱藏了這種模式。如果您想要精確地匹配以 a 開頭和以 b 結尾的一條三個字母的字符串,則您必須對正規表達式進行定位。脱字符號 (^) 元字符指示一行的開始,而美元符號 ($) 指示一行的結尾(參見表1:附表見第4頁)。因此, 正規表達式 ^a.b$ 匹配字符串 aab、abb 或 axb。將這種方式與 LIKE 操作符提供的類似的模式匹配 a_b 相比較,其中 (_) 是單字符通配符
默認情況下,一個正規表達式中的一個單獨的字符或字符列表只匹配一次。為了指示在一個正規表達式中多次出現的一個字符,您可以使用一個量詞,它也被稱為重複操作符。.如果您想要得到從字母 a 開始並以字母 b 結束的匹配模式,則您的正規表達式看起來像這樣:^a.*b$。* 元字符重複前面的元字符 (.) 指示的匹配零次、一次或更多次。LIKE 操作符的等價的模式是 a%b,其中用百分號 (%) 來指示任意字符出現零次、一次或多次。
表 2 給出了重複操作符的完整列表。注意它包含了特殊的重複選項,它們實現了比現有的 LIKE 通配符更大的靈活性。如果您用圓括號括住一個表達式,這將有效地創建一個可以重複一定次數的子表達式。例如,正規表達式 b(an)*a 匹配 ba、bana、banana、yourbananasplit 等。
Oracle 的正規表達式實施支持 POSIX (可移植操作系統接口字符類,參見表 3 中列出的內容。這意味着您要查找的字符類型可以非常特別。假設您要編寫一條僅查找非字母字符的 LIKE 條件 — 作為結果的 WHERE 子句可能不經意就會變得非常複雜。
POSIX 字符類必須包含在一個由方括號 ([]) 指示的字符列表中。例如,正規表達式 [[:lower:]] 匹配一個小寫字母字符,而 [[:lower:]] 匹配五個連續的小寫字母字符。
除 POSIX 字符類之外,您可以將單獨的字符放在一個字符列表中。例如,正規表達式 ^ab[cd]ef$ 匹配字符串 abcef 和 abdef。必須選擇 c 或 d。
除脱字符 (^) 和連字符 (-) 之外,字符列表中的大多數元字符被認為是文字。正規表達式看起來很複雜,這是因為一些元字符具有隨上下文環境而定的多重含義。^ 就是這樣一種元字符。如果您用它作為一個字符列表的第一個字符,它代表一個字符列表的非。因此,[^[:digit:]] 查找包含了任意非數字字符的模式,而 ^[[:digit:]] 查找以數字開始的匹配模式。連字符 (-) 指示一個範圍,正規表達式 [a-m] 匹配字母 a 到字母 m 之間的任意字母。但如果它是一個字符行中的第一個字符(如在 [-afg] 中),則它就代表連字符
之前的一個例子介紹了使用圓括號來創建一個子表達式;它們允許您通過輸入更替元字符來輸入可更替的選項,這些元字符由豎線 (|) 分開。
例如,正規表達式 t(a|e|i)n 允許字母 t 和 n 之間的三種可能的字符更替。匹配模式包括如 tan、ten、tin 和 Pakistan 之類的字,但不包括 teen、mountain 或 tune。作為另一種選擇,正規表達式 t(a|e|i)n 也可以表示為一個字符列表 t[aei]n。表 4 彙總了這些元字符。雖然存在更多的元字符,但這個簡明的概述足夠用來理解這篇文章使用的正規表達式。

正規表達式後向引用

正規表達式的一個有用的特性是能夠存儲子表達式供以後重用;這也被稱為後向引用(在表 10 中對其進行了概述)。它允許複雜的替換功能,如在新的位置上交換模式或顯示重複出現的單詞或字母。子表達式的匹配部分保存在臨時緩衝區中。緩衝區從左至右進行編號,並利用 \digit 符號進行訪問,其中 digit 是 1 到 9 之間的一個數字,它匹配第 digit 個子表達式,子表達式用一組圓括號來顯示。
接下來的例子顯示了通過按編號引用各個子表達式將姓名 Ellen Hildi Smith 轉變為 Smith, Ellen Hildi。
SELECT REGEXP_REPLACE(

'Ellen Hildi Smith',

'(.*) (.*) (.*)', '\3, \1 \2')

FROM dual

REGEXP_REPLACE('EL

------------------

Smith, Ellen Hildi
該 SQL 語句顯示了用圓括號括住的三個單獨的子表達式。每一個單獨的子表達式包含一個匹配元字符 (.),並緊跟着 * 元字符,表示任何字符(除換行符之外)都必須匹配零次或更多次。空格將各個子表達式分開,空格也必須匹配。圓括號創建獲取值的子表達式,並且可以用 \digit 來引用。第一個子表達式被賦值為 \1 ,第二個 \2,以此類推。這些後向引用被用在這個函數的最後一個參數 (\3, \1 \2) 中,這個函數有效地返回了替換子字符串,並按期望的格式來排列它們(包括逗號和空格)。表 11 詳細説明了該正規表達式的各個組成部分。
後向引用對替換、格式化和代替值非常有用,並且您可以用它們來查找相鄰出現的值。接下來的例子顯示了使用 REGEP_SUBSTR 函數來查找任意被空格隔開的重複出現的字母數字值。顯示的結果給出了識別重複出現的單詞 is 的子字符串。
SELECT REGEXP_SUBSTR(

'The final test is is the implementation',

'([[:alnum:]]+)([[:space:]]+)\1') AS substr

FROM dual

SUBSTR

------

is is

正規表達式匹配參數選項

您可能已經注意到了正規表達式操作符和函數包含一個可選的匹配參數。這個參數控制是否區分大小寫、換行符的匹配和保留多行輸入。

正規表達式實際應用

您不僅可以在隊列中使用正規表達式,還可以在使用 SQL 操作符或函數的任何地方(比如説在 PL/SQL 語言中)使用正規表達式。您可以編寫利用正規表達式功能的觸發器,以驗證、生成或提取值。
接下來的例子演示了您如何能夠在一次列檢查約束條件中應用 REGEXP_LIKE 操作符來進行數據驗證。它在插入或更新時檢驗正確的社會保險號碼格式。如 123-45-6789 和 123456789 之類格式的社會保險號碼對於這種列約束條件是可接受的值。有效的數據必須以三個數字開始,緊跟着一個連字符,再加兩個數字和一個連字符,最後又是四個數字。另一種表達式只允許 9 個連續的數字。豎線符號 (|) 將各個選項分開。
ALTER TABLE students
ADD CONSTRAINT stud_ssn_ck CHECK
(REGEXP_LIKE(ssn,
'^([[:digit:]]-[[:digit:]]-[[:digit:]]|[[:digit:]])$'))
由 ^ 和 $ 指示的開頭或結尾的字符都是不可接受的。確保您的正規表達式沒有分成多行或包含任何不必要的空格,除非您希望格式如此並相應地進行匹配。表 12 説明了該正規表達式示例的各個組成部分。

正規表達式功能比較

正規表達式有幾個優點優於常見的 LIKE 操作符和 INSTR、SUBSTR 及 REPLACE 函數的。這些傳統的 SQL 函數不便於進行模式匹配。只有 LIKE 操作符通過使用 % 和 _ 字符匹配,但 LIKE 不支持表達式的重複、複雜的更替、字符範圍、字符列表和 POSIX 字符類等等。此外,新的正規表達式函數允許檢測重複出現的單詞和模式交換。這裏的例子為您提供了正規表達式領域的一個概覽,以及您如何能夠在您的應用程序中使用它們。

正規表達式豐富工具包

因為正規表達式有助於解決複雜的問題,所以它們是非常強大的。正規表達式的一些功能難於用傳統的 SQL 函數來仿效。當您瞭解了這種稍顯神秘的語言的基礎構建程序塊時,正規表達式將成為您的工具包的不可缺少的一部分(不僅在 SQL 環境下也在其它的編程語言環境下)。為了使您的各個模式正確,雖然嘗試和錯誤有時是必須的,但正規表達式的簡潔和強大是不容置疑的。
正規表達式詳細定義
正規表達式(regular expression)描述了一種字符串匹配的模式,可以用來檢查一個串是否含有某種子串、將匹配的子串做替換或者從某個串中取出符合某個條件的子串等。
列目錄時, dir *.txt或ls *.txt中的*.txt就不是一個正規表達式,因為這裏*與正規式的*的含義是不同的。
正規表達式是由普通字符(例如字符 a 到 z)以及特殊字符(稱為元字符)組成的文字模式。正規表達式作為一個模板,將某個字符模式與所搜索的字符串進行匹配。
1. 普通字符
由所有那些未顯式指定為元字符的打印和非打印字符組成。這包括所有的大寫和小寫字母字符,所有數字,所有標點符號以及一些符號。
2. 非打印字符 字符 含義
\cx 匹配由x指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須為 A-Z 或 a-z 之一。否則,將 c 視為一個原義的 'c' 字符。
\f 匹配一個換頁符。等價於 \x0c 和 \cL。
\n 匹配一個換行符。等價於 \x0a 和 \cJ。
\r 匹配一個回車符。等價於 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]。
\S 匹配任何非空白字符。等價於 [^ \f\n\r\t\v]。
\t 匹配一個製表符。等價於 \x09 和 \cI。
\v 匹配一個垂直製表符。等價於 \x0b 和 \cK。
3.  特殊字符
所謂特殊字符,就是一些有特殊含義的字符,如上面説的"*.txt"中的*,簡單的説就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對*進行轉義,即在其前加一個\。ls \*.txt。正規表達式有以下特殊字符。
特別字符 説明
$ 匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,請使用 \$。
( ) 標記一個子表達式的開始和結束位置。子表達式可以獲取供以後使用。要匹配這些字符,請使用 \( 和 \)。
* 匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 \*。
+ 匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 \+。
. 匹配除換行符 \n之外的任何單字符。要匹配 .,請使用 \。
[ 標記一箇中括號表達式的開始。要匹配 [,請使用 \[。
? 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 \?。
\ 將下一個字符標記為或特殊字符、或原義字符、或向後引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。
^ 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 \^。
{ 標記限定符表達式的開始。要匹配 {,請使用 \{。
| 指明兩項之間的一個選擇。要匹配 |,請使用 \|。
構造正規表達式的方法和創建數學表達式的方法一樣。也就是用多種元字符與操作符將小的表達式結合在一起來創建更大的表達式。正規表達式的組件可以是單個的字符、字符集合、字符範圍、字符間的選擇或者所有這些組件的任意組合。
4.  限定符
限定符用來指定正規表達式的一個給定組件必須要出現多少次才能滿足匹配。有*或+或?或或{n,}或{n,m}共6種。
*、+和?限定符都是貪婪的,因為它們會盡可能多的匹配文字,只有在它們的後面加上一個?就可以實現非貪婪或最小匹配。
正規表達式的限定符有:
字符 描述
* 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價於{0,}。
+ 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價於 {1,}。
? 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價於 {0,1}。
n 是一個非負整數。匹配確定的 n 次。例如,'o' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的兩個 o。
{n,} n 是一個非負整數。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等價於 'o+'。'o{0,}' 則等價於 'o*'。
{n,m} m 和 n 均為非負整數,其中n≤m。最少匹配 n 次且最多匹配 m 次。例如,"o{1,3}" 將匹配 "fooooood" 中的前三個 o。'o{0,1}' 等價於 'o?'。請注意在逗號和兩個數之間不能有空格。
5.  定位符
用來描述字符串或單詞的邊界,^和$分別指字符串的開始與結束,\b描述單詞的前或後邊界,\B表示非單詞邊界。不能對定位符使用限定符
6.  選擇
用圓括號將所有選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個副作用,是相關的匹配會被緩存,此時可用?:放在第一個選項前來消除這種副作用。
其中?:是非捕獲元之一,還有兩個非捕獲元是?=和?!,這兩個還有更多的含義,前者為正向預查,在任何開始匹配圓括號內的正規表達式模式的位置來匹配搜索字符串,後者為負向預查,在任何開始不匹配該正規表達式模式的位置來匹配搜索字符串。
7.  後向引用
對一個正規表達式模式或部分模式兩邊添加圓括號將導致相關匹配存儲到一個臨時緩衝區中,所捕獲的每個子匹配都按照在正規表達式模式中從左至右所遇到的內容存儲。存儲子匹配的緩衝區編號從 1 開始,連續編號直至最大 99 個子表達式。每個緩衝區都可以使用 '\n' 訪問,其中 n 為一個標識特定緩衝區的一位或兩位十進制數。
可以使用非捕獲元字符 '?:', '?=', or '?!' 來忽略對相關匹配的保存。