MySQL正則表達式

一.簡介

正則表達式的作用是匹配文本,將一個模式(正則表達式)與一個文本串進行比較。MySQL用where子句對正則表達式提供支持,允許指定正則表達式過濾select檢索出的數據。

二.基本字符匹配

輸入

select name from product where name regexp '1';

輸出

輸出.png

分析

除關鍵字like被regexp替代外,這條語句看上去像like語句。它告訴MYSQL:REGEXP后所跟的東西作為正則表達式處理。
為什么要費力地使用正則表達式?在剛才的例子中,正則表達式確實沒有帶來太多好處(可能還會降低性能),不過,請考慮下面的例子:

輸入

select name from product where name regexp '.22';

輸出

輸出.png

分析

這里使用了正則表達式 .22。.是正則表達式語言中一個特殊的字符。它表示匹配任意一個字符,因此,322和122都匹配且返回。

Like與REGEXP 在LIKE和REGEXP之間有一個重要的差別。
請看以下兩條語句:
select name 
from product
where name like '322';

select name 
from product
where name regexp '322';

如果執行上述兩條語句,會發現第一條語句不返回數據,而第二條語句返回一行。為什么?
這是因為like匹配整個列。如果被匹配的文本在列值中出現,like將不會找到它,相應的行也不被返回(除非使用通配符)。而regexp在列值內進行匹配,如果被匹配的文本在列值中出現,regexp將會找到它,相應的行將被返回。這是一個非常重要的差別。
那么,regexp能不能用來匹配整個列值(從而起與like相同的作用)?答案是肯定的,使用^和$定位符即可。
匹配不區分大小寫  MySQL中的正則表達式匹配(自版本3.23.4后)不區分大小寫(即,大小寫都匹配)。為區分大小寫,可使用BINARY關鍵字,如where name regexp binary 'Product.22'.

三.進行OR匹配

為搜索兩個串之一(或者為這個串,或者為另一個串),使用|,如下所示:

輸入

select name from product where name regexp '122|322';

輸出

輸出.png

分析

語句中使用了正則表達式122|322。|為正則表達式的OR操作符。它表示匹配其中之一,因此122和322都匹配并返回。
使用|從功能上類似于select語句中使用OR語句,多個OR條件可并入單個正則表達式。

兩個以上的OR條件 可以給出兩個以上的OR條件。例如,‘122|322|422’將匹配122或322或422

四.匹配幾個字符之一

匹配任何單一字符。但是,如果你只想匹配特定的字符,怎么辦?可通過指定一組【和】括起來的字符來完成,如下所示:

輸入

select name from product where name regexp '[123] pro';

輸出

輸出.png

分析

這里,使用了正則表達式[123] pro。[123]定義一組字符,它的意思是匹配1或2或3,因此,1 pro和2 pro都匹配且返回(沒有3 pro)。
正如所見,[]是另一種形式的OR語句。事實上,正則表達式[123] pro為[1|2|3] pro的縮寫,也可以使用后者。但是,需要是[]來定義OR語句查找什么。為更好理解這一點,可以查看下面的例子:

輸入

select name from product where name regexp '1|2|3 pro';

輸出

輸出.png

分析

這并不是期望的輸出。兩個要求的行被檢索出來,但還檢索出了另外3行。之所以這樣是由于MySQL假定你的意思是'1'或'2'或'3 pro'。除非把字符|括在一個集合中,否則它將應用于整個串。
字符集合也可以被否定,即,它們將匹配除指定字符外的任何東西。為否定一個字符集,在集合的開始處放置一個即可。因此,盡管[123]匹配字符1、2或3,但[123]卻匹配除這些字符外的任何東西。

五.匹配范圍

集合可用來定義要匹配的一個或多個字符。例如,下面的集合將匹配數字0到9:
[0123456789]
為簡化這種類型的集合,可使用-來定義一個范圍。下面的式子功能上等同于上述數字列表:
[0-9]
范圍不限于完整的集合,[1-3]和[6-9]也是合法的范圍。此外,范圍不一定只是數值的,[a-z]匹配任意字母字符。
例子如下

輸入

select name from product where name regexp '[1-4] pro';

輸出

輸出.png

分析

這里使用正則表達式[1-4] pro。[1-4]定義了一個范圍,這個表達式意思是匹配1到4.因此返回3個匹配行。由于3 pro匹配,所以返回y3 pro apple。

六.匹配特殊字符

正則表達式語言由具有特定含義的特殊字符構成。我們已經看到“.”、“[]”、“|”和“-”等,還有其他一些字符。請問,如果你需要匹配這些字符,應該怎么辦呢?例如,如果要找出包含“.”字符的值,怎么搜索?請看下面的例子:

輸入

select name from product where name regexp '.';

輸出

輸出.png

分析

這并不是期望的輸出,.匹配任意字符,因此每個行都被檢索出來
為了匹配特殊字符,必須使用\\為前導。\\-表示查找-,\\.表示查找.。

輸入

select name from product where name regexp '\\.';

輸出

輸出.png

分析

這才是期望的輸出。\\.匹配.,所以只檢索出一行。這種處理就是所謂的轉義,正則表達式內具有特殊意義的所有字符都必須以這種方式轉義。這包括“.”、“|”、“[]”以及至今為止使用過的其他特殊字符。
\\也用來引用元符號(具有特殊含義的字符),如下面所列。

元字符 說明
\\f 換頁
\\n 換行
\\r 回車
\\t 制表
\\v 縱向制表
匹配\   為了匹配反斜杠(\)字符本身,需要使用\\\
\或\\?   多數正則表達式實現使用單個反斜杠轉義特殊字符,以便能使用這些字符本身。但MySQL要求兩個反斜杠(MySQL自己解釋一個,正則表達式解釋另一個)

七.匹配字符類

存在找出你自己經常使用的數字、所有字母字符或所有數字字母字符等的匹配。為更方便工作,可以使用預定義的字符集,稱為字符類。下面列出字符類以及它們的含義。

元字符 說明
[:alnum:] 任意字母和數字(同[a-zA-Z0-9])
[:alpha:] 任意字符(同[a-zA-Z])
[:blank:] 空格和制表(同[\\t])
[:cntrl:] ASCII控制字符(ASCII 0到31和127)
[:digit:] 任意數字(同[0-9])
[:graph:] 與[:print:]相同,但不包括空格
[:lower:] 任意小寫字母(同[a-z])
[:print:] 任意可打印字符
[:punct:] 既不在[:alnum:]又不在[:cntrl:]中的任意字符
[:space:] 包括空格在內的任意空白字符(同[\\f\\n\\r\\t\\v])
[:upper:] 任意大寫字母(同[A-Z])
[:xdigit:] 任意十六進制數字(同[a-fA-F0-9])

八.匹配多個實例

目前為止使用的所有正則表達式都試圖匹配單次出現。如果存在一個匹配,該行被檢索出來,如果不存在,檢索不出任何行。但有時需要對匹配的數目進行更強的控制。例如,你可能需要尋找所有的數,不管數中包含多少數字,或者你可能想尋找一個單詞并且還能適應一個尾隨的s(如果存在),等等。
這可以使用下面的正則表達式重復元字符來完成。

元字符 說明
* 0個或多個匹配
+ 1個或多個匹配(等于{1,})
? 0個或1個匹配(等于{0,1})
{n} 指定數目的匹配
{n,} 不少于指定數目的匹配
{n,m} 匹配數目的范圍(m不超過255)

下面舉幾個例子。

輸入

select name from product where name regexp '\\([0-9] sticks?\\)';

輸出

輸出.png

分析

正則表達式\\([0-9] sticks?\\)需要解說一下。\\(匹配),[0-9]匹配任意數字(這個例子中為1和5),sticks?匹配stick和sticks(s后的?使s可選,因為?匹配它前面的任何字符的0次或1次出現),\\)匹配)。沒有?,匹配stick和sticks會非常困難。
以下是另一個例子。匹配連在一起的3位數字:

輸入

select name from product where name regexp '[[:digit:]]{3}';

輸出

輸出.png

分析

如前所述,[:digit:]匹配任意數字,因而它為數字的一個集合。{3}確切地要求它前面的字符(任意數字)出現3次,所以[[:digit:]]{3}匹配連在一起的任意三位數字。
上面的式子也可以改成下面這種形式

select name from product where name regexp '[0-9][0-9][0-9]';

九.定位符

上述的所有例子都是匹配一個串中任意位置的文本。為了匹配特定位置的文本,需要下面的定位符。

元字符 說明
^ 文本的開始
$ 文本的結尾
[[:<:]] 詞的開始
[[:>:]] 詞的結尾

例如,如果你想找出以一個數(包括以小數點開始的數)開始的所有產品,怎么辦?簡單搜索[0-9\\.] (或[[:digit:]\\.])不行,因為它將在文本內任意位置查找匹配。解決辦法就是使用^定位符,如下所示:

輸入

select name from product where name regexp '^[0-9\\.]';

輸出

輸出.png

分析

匹配串的開始。因此,[0-9\\.]只在.或任意數字為串中第一個字符時才匹配它們。沒有^,則還要多檢索出4個別的行(那些中間有數字的行)。

^的雙重用途  ^有兩種用法。
在集合中(用[和]都定義),用它來否定該集合,否則,用來指串的開始處。
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,117評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,860評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,128評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,291評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,025評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,421評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,477評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,642評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,177評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,970評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,157評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,717評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,410評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,821評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,053評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,896評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,157評論 2 375