正則表達式基礎

原作者:工匠若水

一、概述

正則表達式使用單個字符串來描述、匹配一系列符合某個句法規則的字符串。在很多文本編輯器裏,正則表達式通常被用來檢索、替換那些符合某個模式的文本。由於正則表達式主要應用對象是文本,因此它在各種文本編輯器場合都有應用,小到著名編輯器EditPlus,大到Microsoft Word、Visual Studio等大型編輯器,都可以使用正則表達式來處理文本內容。(PS:初學者一般都認爲正則表達式非常抓狂的!理解,你會發現他的強大!)

給定一個正則表達式和另一個字符串,我們可以達到如下的目的:

給定的字符串是否符合正則表達式的過濾邏輯(稱作“匹配”);
可以通過正則表達式,從字符串中獲取我們想要的特定部分。
正則表達式的特點是:

靈活性、邏輯性和功能性非常的強;
可以迅速地用極簡單的方式達到字符串的複雜控制。
對於剛接觸的人來說,比較晦澀難懂。
開始學習前的裝逼工具技能:

1、正則表達式在線驗證工具推薦regexpal

這裏寫圖片描述

Regexpal是一個基於Javascript的在線正則表達式驗證工具,上面的輸入框中,是讓我們輸入正則表達式(匹配規則),下面的輸入框則是讓我們輸入待匹配的數據。此外,根據具體要求,還可以設置忽略大小寫、多行匹配等參數。

2、本地安裝工具推薦 regexbuddy3

這裏寫圖片描述

RegexBuddy一款正則表達式編輯工具,幫助你的編寫需要的正則表達式,還可以使用它理解別人編寫的表達式。

3、學習裝逼的工具regexr

不解釋,自己Google吧。

總結:

工具使用不多解釋,這都是小兒科工具,碼農都可以自己搞定的。接下來繼續帶你裝逼帶你飛。

二、模式匹配基礎

匹配字符串字面值:

原始字符串:”yanbo”
正則表達式:”yanbo”

如上就是最簡單最直接的字面匹配字符串,屬於最簡單的正則表達式。

匹配數字:

正則表達式: “\d” 或者 “[0-9]” 或者 “[0123456789]”
原始字符串:”3”

如上三個正則表達式的匹配效果是一樣的,都是匹配指定字串中的一個0-9的數字,只是匹配一個數字。三種寫法各有優勢,”\d”可以表示任意數字,”[m-n]”可以表示m-n的一位數字,”[abcd]”可以匹配指定的abcd中的一個數字。特別的認爲”[0123456789]”匹配的是”0123456789”字符串是錯誤的想法,特別留意,匹配的是一位!!!還可以如下:

正則表達式:”[015-7]”
可匹配的數字:0,1,5,6,7

匹配非數字字符:

正則表達式:”\D” 或者 “[^0-9]” 或者 “[^\d]”
匹配字串:非數字字符(切記:也是匹配一個字符)。

如上三個正則表達式的匹配效果是一樣的,都是匹配一個非數字字符。”[]”中的”^”就是取反,除去”^”後面的內容。

匹配單詞和非單詞字符:

首先強調一點,匹配的是單詞和非單詞的字符,不是單詞!!!

“\w” 這個簡寫式將匹配所有單詞字符(字母、數字、下劃線)。
“\D” 匹配非數字字符,包含空格、標點(引號、連字符、反斜槓、方括弧)等字符。
在英語環境下 “\w” 與 “[_a-z0-9A-Z]” 匹配相同的單詞字符。
“\W” 匹配非單詞字符(空格、標點及其他非字母、數字字符等)。
在英語環境下 “\W” 與 “[^_a-z0-9A-Z]” 匹配相同的單詞字符。

如下提供更多的字符簡寫式,不過要注意!!!!不是所有的正則表達式處理器可以識別以下簡寫式。

字符簡寫式 描述
\a 報警符
[\b] 退格字符
\c x 控制字符
\d 數字符
\D 非數字符
\w 單詞字符
\W 非單詞字符
\0 空字符
\x xx 字符的十六進制值
\u xxx 字符的Unicode值
匹配空白符與非空白符:

正則表達式:”\s” 或者 “[ \t\n\r]”
匹配結果: 空白符(空格、製表符、換行符、回車符)

如上 “[ \t\n\r]” 的 “\t\n\r” 前至少有一個空格,否則無效。

正則表達式:”\S” 或者 “[^\s]” 或者 “[^ \t\n\r]”
匹配結果: 非空白符(除空格、製表符、換行符、回車符以外的字符)。

除過 “\s” 匹配的字符之外還有如下一些不太常見的空白符:

字符簡寫式 描述
\s 空白符
\S 非空白符
\f 換頁符
\h 水平空白符
\H 非水平空白符
\n 換行符
\r 回車符
\t 水平製表符
\v 垂直製表符
\V 非垂直製表符

匹配任意符:

“.” 匹配除過行結束符以外的所有字符,個別情況除外。

正則表達式:”\b\w\w\w\b”
匹配字符串:三個字符的單詞

如上表達式中”\b”簡寫式匹配單詞邊界,不消耗任何字符,一般兩個邊界都寫。如下例子是”.”的特例。

正則表達式: "a.c\."
匹配字符串:axc.

如上匹配的是axc. 其中x可以是任意字符,而最後 . 就是轉義字符而不是 . 。

實戰裝逼展示:

學習了一些入門級的正則表達式以後我們就來裝裝逼,裝逼也要裝的有逼格,所以如上第一章的工具就太簡單了,我們用Linux的sed流編輯器來裝逼。(PS:不瞭解Linux的sed流編輯器的請自己google或者度娘)。

這裏演示一個將字符串”This is YanBo’s Blog!”以Html二級標題輸出的例子。

sed編輯器命令:

echo "This is YanBo's Blog!" | sed 's/^/<h2>/;s/$/<\/h2>/p;q'

如上命令在linux終端執行之後如下:

  1. echo打印”This is YanBo’s Blog!”到屏幕,然後通過”|”管道將輸出作爲sed的輸入。
  2. sed默認操作是直接複製每行輸入並輸出。
  3. s/^/<h2>/在行的開頭(^)添加HTML的二級標題<h2>標籤。
  4. 分號(;)用於分割命令。
  5. s/$/<\/h2>/用於在結尾($)添加HTML二級標題</h2>標籤。
  6. 命令p打印受影響的一行。
  7. 命令q結束sed程序。

總結:

這一部分我們學習正則表達式的基礎匹配,算是入門技能。接下來繼續帶你裝逼帶你飛。

三、正則表達式—邊界

熱身準備:

不多BB,邊界這部分算是正則表達式的核心之一。斷言(零寬度斷言)這一詞足矣。

斷言(零寬度斷言)標記邊界,並不耗費字符,不匹配字符,匹配字符串中的位置。

字符串或者行起始與結束:

“^” 匹配行或者字符串的起始位置,或者整個文檔的起始位置。
“$” 匹配行或者字符串結尾位置。

例子:
正則表達式: “^word$”
匹配字符串: word(僅有該單詞的字符串,w開頭,d結束)。

單詞編輯與非單詞邊界:

“\bxxx\b” 匹配單詞邊界。

“\b” 是一個零寬度斷言,表面上它會匹配空格或者行起始,實際上它匹配的是一個零寬度不存在的東西。

“\B” 是一個匹配非單詞邊界,匹配除單詞之外的位置。

例子:
正則表達式: “\Ba\B”
匹配字符串: “fhrrhahhr”(類似這樣的a兩邊不是單詞邊界的字符,這裏匹配字符a)。

其他錨位符:

“\A” 與”^”相似,該錨位符匹配主題詞的開始。這個寫法不是在所有的正則表達式程序中都可以使用的,但是可以在Perl和PCRE中使用,要匹配主題詞的結尾用”\Z”, 某些上下文中還可以用”\z”。

例子:
正則表達式:”\Aaaaa\Z”
匹配字串:”aaaa” (僅僅aaaa開頭結尾的字符串,也即主題詞開始結束)

使用元字符的字面值:

可以用”\Q”和”\E”之間的字符集匹配字符串字面值。”.^$*+?|(){}[]-“這15個元字符在正則表達式中有特殊含義,用來編寫匹配模式。其中的連字符”-“在正則表達式的方括號中用來表示範圍,其他情況下無特殊含義。你在正則表達式中直接輸入這些字符不會顯示,如果想顯示這些字符本身你就需要把他放在”\Q”和”\E”之間,當然,也可以在其前面加”\”即可。

例子:
正則表達式: "\Q$\E" 或者 "\$"
匹配字符: $字符本身

實戰裝逼一把:

繼續像上一節一樣裝逼,繼續添加標籤,繼續使用linux的sed命令BB。sed中的命令(i)允許你在文件或者字符串中的某個位子之前插入文本,與(i)相反的命令是(a),他是在某個位置之後添加文本。關於sed(或者grep或者vi與vim)的實戰正則表達式例子這裏不給出,自行google嘗試,這裏重在講解正則表達式。

總結:

學習了邊界與斷言(零寬度斷言)。沒啥總結的,開始正則表達式的精華,繼續BB。

四、選擇、分組和後向引用

選擇操作:

選擇操作可以在多個可選模式中匹配一個。譬如你想在”The android developer need fix bug on the Bug System.”中找出”the”(the, The, THE)出現過多少次,這時候就使用選擇模式。

正則表達式:”(the|The|THe|THE|tHE|thE|ThE|tHe)” 或者 “(?i)the”
原始字符串:”The android developer need fix bug on the Bug System.”
匹配結果: The,the

如上正則表達式匹配所有大小寫的the。

以下是其他各種選項和修飾符(注意:如下選項不實用所有正則表達式的平臺):

選項 描述 支持平臺
(?d) unix中的行 java
(?i) 不區分大小寫 PCRE、Perl、Java
(?J) 允許重複的名字 PCRE
(?m) 多行 PCRE、Perl、Java
(?s) 單行(dotall) PCRE、Perl、Java
(?u) Unicode java
(?U) 默認最短匹配 PCRE
(?x) 忽略空格和註釋 PCRE、Perl、Java
(?-…) 復原或者關閉選項 PCRE

子模式:

子模式是正則表達式分組中的一個或者多個分組,就是模式中的模式。多數情況,子模式中的條件能得到匹配的前提是前面的模式得到匹配,但是也有例外(譬如”(the|THE|The)”匹配THE不依賴於the,因爲the會先去匹配,這個例子有三個子模式,分別是the、THE、The),子摸式寫法很多種,這裏只關注括弧中的子模式。

例子(子模式匹配依賴於前面的模式):

正則表達式:(t|T)h(e|E)
匹配:the、The、thE、ThE

上面例子中第二個子模式”(e|E)”依賴於第一個子模式”(t|T)”。

特別的,括弧對於子模式不是必須的!!!!!如下:

正則表達式:”\b[tT]h[eE]”
匹配:the、The、thE、ThE

以上”[tT]”字符組可以看作第一個子模式,同理第二個。

捕獲分組和後向引用:

當一個模式的全部或者部分內容由一對括號分組時,他就對內容進行捕獲並臨時存儲於內存中,可以通過後向引用重用捕獲的內容,形式如下:

“\1” 、”\2” 或者 “1”、”2”,捕獲的n個分組。

在sed命令中只接受”\1”這種分組。

例子(使用linux的sed命令模擬後向引用):

echo "YanBo is an Android Developer!" | sed -En 's/(YanBo is) (an Android Developer)/\2 \1/p'

輸出:an Android Developer YanBo is!
解釋:
-E 是sed調運ERE(擴展正則表達式),因此,括號可以當作字面值來使用。
-n 覆蓋打印每一行的默認設置。
捕獲分組1,2進行替換。

命名分組:

命名分組就是有名字的分組。由此可以通過名字引用分組而不是數字。

命名分組語法:

語法 描述
(?…) 命名分組
(?name…) 另一種命名分組方式
(?P…) Python中的命名分組
\k 在Perl中引用分組名
\k’name’ 在Perl中引用分組名
\g{name} 在Perl中引用分組名
\k{name} 在.NET中引用分組名
(?P=name) 在Python中引用分組名

非捕獲分組:**

非捕獲分組不會將其內容存儲在內存中。在你並不想引用分組時可以使用它。由於不存儲分組,所以非捕獲分組性能較高。

例子:

捕獲分組的寫法:”(the|THE|The)”
不需要任何後向引用可以寫爲:”(?:the|The|THE)”
不區分大小寫:”(?i)(?:the)” 或者 “(?:(?i)the)” 或者(推薦)”(?i:the)”

原子分組:

還有一種非捕獲分組時原子分組。如果你用正則表達式引擎進行回朔操作,這種分組可以關閉回朔操作,但是他只爭對原子分組部分,而不是整個表達式。語法如下:

“(?>the)”

正則表達式慢的一個原因就是回朔操作。

總結:

沒啥總結的,繼續裝逼繼續飛,下面的逼格更高更嗨!!!

六、正則表達式—量詞

貪心、懶惰、佔有:

量詞本來是貪心的。貪心量詞首先會匹配整個字串,然後一個一個回退(回朔),直到找到匹配的爲止。所以他最消耗資源。

懶惰的量詞使用另一種策略,他從目標的起始位置開始尋找匹配,每次檢查一個字符,最後嘗試匹配整個字符串。想要量詞變爲懶惰的,必須在普通量詞後添加一個問號(?)。

佔有量詞會覆蓋整個目標然後嘗試尋找匹配內容,但是隻嘗試一次,不會回朔。佔有量詞是在普通量詞之後添加一個加號(+)。

正則表達式*、+、?進行匹配:

如下基本量詞默認都是貪心的。

語法 描述
? 零個或者一個
+ 一個或者多個
* 零個或者多個

例如:
正則表達式:”9+”
匹配:一個或者多個9

匹配特定次數:

如下花括弧量詞是匹配最精確的量詞,默認也是貪心的。

語法 描述
{n} 精確匹配n次
{n,} 匹配n或者更多次
{m,n} 匹配m-n次
{0,1} 與?相同,零次或一次
{1,0} 與+相同,一次或更多
{0,} 與*相同,零次或者更多

懶惰量詞:

這個懶惰量詞直接實戰來說:

正則表達式:”8?”
匹配:一個或者0個8

正則表達式:”8??” (懶惰)
匹配:一個8都沒匹配,因爲懶惰,儘可能少。

正則表達式:”8*?” (懶惰)
匹配:一個8都沒匹配,因爲懶惰,儘可能少。

正則表達式:”8+?” (懶惰)
匹配:匹配了一個8。

正則表達式:”8{3,8}?” (懶惰)
匹配:匹配了三個8。

懶惰量詞表:

語法 描述
?? 懶惰匹配0-1次
+? 懶惰匹配1-多次
*? 懶惰匹配0-多次
{n}? 懶惰匹配多次
{n,}? 懶惰匹配n-多次
{m,n}? 懶惰匹配m-n次

佔有量詞:

佔有量詞表:

語法 描述
?+ 佔有匹配0-1次
++ 佔有匹配1-多次
*+ 佔有匹配0-多次
{n}+ 佔有匹配多次
{n,}+ 佔有匹配n-多次
{m,n}+ 佔有匹配m-n次

例子:

正則表達式:”1.*+”
匹配:所有的1全被高亮。

正則表達式:”.*+1”
匹配:沒有匹配,因爲沒有回朔。

正則表達式:”.*1”
匹配:匹配末尾爲1的字串,貪心模式。

總結:

這裏介紹的量詞算是正則表達式效率方面的精華所在,沒啥解釋的,繼續裝逼繼續飛。

七、正則表達式—環視

環視是非捕獲分組,也稱作零寬斷言。

正前瞻:

例子:

正則表達式:”(?i)aaa (?=bbb)”
原始串:”aaa ccc bbb aaa bbb ccc aaa”
匹配:只匹配第二處”aaa”。

以上就是匹配aaa,同時要求aaa單詞之後緊隨的是bbb。使用了正前瞻達到目的。

反前瞻:

反前瞻是正前瞻的取反操作。

例子:

正則表達式:”(?i)aaa (?!bbb)”
原始串:”aaa ccc bbb aaa bbb ccc”
匹配:只匹配第一處”aaa”。

以上就是匹配aaa,同時要求aaa單詞之後緊隨的不能是bbb。使用了反前瞻達到目的。

正後顧:

正後顧與正前瞻方向相反。

例子:

正則表達式:”(?<=aaa) bbb”
原始串:”aaa ccc bbb aaa bbb ccc aaa ”
匹配:只匹配第二處”bbb”。

反後顧:

反後顧與反前瞻方向相反。

例子:

正則表達式:”(?

總結:

這塊更加不需要BB總結,就是例子理解,照貓畫虎就行。

大結局

整個正則表達式基礎到這就差不多夠用了。總結學習方法就是大膽實踐,多亂想然後編輯器驗證就行了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章