正则表达式笔记(一)
正則表達式
- 一、元字符
- 1.1 元字符表
- 1.2 匹配位置的元字符
- 1.2.1 `^`
- 1.2.2 `$`
- 1.2.3 `\b`
- 1.3 匹配字符的元字符
- 二、文字匹配
- 2.1、字符類
- 2.2、限定符
- 2.2.1 `*、+、?`的區別
- 2.2.2懶惰限定符
- 2.3、字符的運算
- 1.3.1 替換 `"|"`
- 2.3.2 分組 `"("和")"`
- 2.3.3 反向引用
- 2.4 零寬斷言
- 匹配HTML
- 匹配HTML標記
- 匹配HTML標記之間的內容
一、元字符
在正則表達式中,元字符(Metacharacter)是一類非常特殊的字符,它能夠匹配一個位置或字符集合中的一個字符,如、\w等。根據功能,元字符可分為兩種類型:匹配位置的元字符和匹配字符的元字符。
1.1 元字符表
如果大家別正則表單式中的字符的作用區分開,可能更好去理解。
| ^ | 匹配字符字符串的開頭 |
| $ | 匹配字符串的末尾 |
| \b | 匹配一個單詞邊界,也就是單詞和空格間的位置。例如:’er\b’可以匹配"never"中的er ,但不能匹配"verb" 中的er |
| . | 匹配除“\n”之外的任何字符。要匹配包括“\n"在內的任何字符,要使用 '[.\n]'的模式 |
| \w | 匹配包括下劃線的任意單詞字符(漢字在內),等價于 ‘[A-Za-z0-9_]’ |
| \W | 匹配任意非單詞字符 ,等價于 ‘[^A-Za-z0-9_]’ |
| \s | 匹配任何空白字符,包括空格,制表符,換頁符。等價于[\f\n\r\t\v] |
| \S | 匹配任意非空字符,等價于[^\f\n\r\t\v] |
| \d | 匹配一個數字字符,等價于[0-9] |
| \D | 匹配一個非數字字符,等價于 [^0-9] |
1.2 匹配位置的元字符
匹配位置的元字符包括3個字符:^、$和\b。其中,^(脫字符號,通常在文章中插入字時使用)和$(美元符號)只匹配一個位置,它們分別匹配行的開始和結尾。
1.2.1 ^
放在字符的前邊。
如下面例子,會匹配以“string"開始的行,且匹配出來的結果只有”string“。
1.2.2 $
放在字符的后邊,和^一樣,也只會匹配到該字符。
如果是
^string$ ^$ //空行則,匹配的行,只有字符串string
1.2.3 \b
元字符\b和^、s具有相似性,它也是匹配一個位置。b可以匹配單詞的開始和結尾,即單詞的分界處。
通常情況下,英文單詞之間往往由空格符號、標點符號或換行符號來分隔,但是元字符\b不匹配空格符號、標點符號和換行符號中的任何一個,它僅僅匹配一個位置。
以下正則表達式匹配以“Str”開頭的字符串,如“String”、“String Format”等。q且只匹配除“Str"
什么理解所說的單詞分界處呢?下面我們來看看這個例子:
可以看到,在單詞里邊的in是沒有被匹配到的,而且有一點,它是以單詞為分界的。如果下面的例子換成^in就什么也匹配不上了。
- .\bmy\b,則會匹配到一個完整的my單詞,如果my出現在一個單詞的開頭是匹配不上的。
1.3 匹配字符的元字符
如果單獨使用只會匹配到一個字符,在上面也提到了
二、文字匹配
2.1、字符類
在正則表達式中,元字符如果沒有量詞的情況下通常一次只能匹配一個位置或字符集合中的一個字符。
通常情況下,如果要匹配數字、字母、空白等字符時,可以直接使用與這些集合相對應的元字符。
然而,如果要匹配的字符集合(如集合[0,1 1,2,3,4,5]) 沒有與之相對應的元字符時,則需要自定義匹配的字符集合。
此時,可以使用字符類解決這個問題。字符類是一個字符集合,如果該字符集合中的任何一個字符被匹配,則它就會找到該匹配項。
字符類是正則表達式中的“迷你”語言,可以在方括號“[ ]”中定義。最簡單的字符類由方括號“[ ]”和一個字母表構成,如元音字符類 [aeiou]。
以下正則表達式匹配數字0、1、2、3、4、5、6中的任何一個。
如果方括號中字母或數字太多就不方便了,那么就可以使用==連接符-==來定義范圍。(范圍是由ASCII表中的順序定義的)
[0-9] //d等價于[0123456789]特殊情況
[-9]只能匹配到9或者-。所以使用連接符必須有始有終。
- 注意: 在字符集中使用元字符時,不會進行轉義運算。就是說元字符的作用消失了。如
只能匹配到.。
2.2、限定符
正則表達式的元字符一次一般只能匹配一個位置或一個字符,如果想要匹配零個、一個或多個字符時,則需要使用限定符。限定符用于指定允許特定字符或字符集自身重復出現的次數。如{n}表示重復n次、{n}表示重復至少n次、{n,m}表示重復至少n次,最多m次。
常用限定符的說明如表1.5所示。
| {n} | n 是一個非負整數。匹配確定的 n 次。例如,‘o{2}’ 不能匹配 “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?’。請注意在逗號和兩個數之間不能有空格。 |
| * | 匹配前面的子表達式零次或多次。例如,zo* 能匹配 “z” 以及 “zoo”。* 等價于{0,}。 |
| + | 匹配前面的子表達式一次或多次。例如,‘zo+’ 能匹配 “zo” 以及 “zoo”,但不能匹配 “z”。+ 等價于 {1,}。 |
| ? | 匹配前面的子表達式零次或一次。例如,“do(es)?” 可以匹配 “do” 或 “does” 中的"do" 。? 等價于 {0,1}。 |
| *? | 盡可能少地使用重復的第一個匹配 |
| +? | 盡可能少地使用重復但至少使用一次 |
| ?? | 使用零次重復(如有可能)或一次重復 |
| {n}? | 等同于{n} |
| {n,}? | 盡可能少地重復使用n次 |
| {n,m}? | 介于n次和m次之間,盡可能少地重復使用 |
2.2.1 *、+、?的區別
通過一個例子展示
?
+
*
通過對比我們可以知道*是+和?的結合體。
2.2.2懶惰限定符
| *? | 盡可能少地使用重復的第一個匹配 |
| +? | 盡可能少地使用重復但至少使用一次 |
| ?? | 使用零次重復(如有可能)或一次重復 |
| {n}? | 等同于{n} |
| {n,}? | 盡可能少地重復使用n次 |
| {n,m}? | 介于n次和m次之間,盡可能少地重復使用 |
這些字符匹配遵循懶惰匹配。如果把?去掉就是貪婪匹配。
- 懶惰匹配,即匹配盡可能少的字符,但是要匹配出所有的結果。
- 檢索結果中,每遇到一次關鍵字,都會停下來,重新檢索。如下面這個例子:
如果是a.*d
結果就是abcdakdjd
這就是貪婪匹配,顧名思義,很貪婪,要最大限度的占用字符串。
以上兩種,一個是盡量匹配最短串,一個是要匹配最長串。
2.3、字符的運算
1.3.1 替換 "|"
最簡單的替換是使用字符|表示,它表示如果某一個字符串匹配了正則表達式中的字符|的左邊或右邊的規則,那么該字符也匹配了該正則表達式。
如
0\d{2}-\d{7}|0\d{3}[-]?\d{7}其中[-]? 表示-可有可無
- 注意:在匹配的時候首先匹配字符的左側部分,如果匹配成功就不匹配了。
2.3.2 分組 "("和")"
分組又稱為子表達式,即把一個正則表達式的全部或部分分成一個或多個組。
其中,分組使用的字符為“(”和“)”,即左圓括號和右圓括號。
分組之后,可將在==“(”和“)”之間==的表達式看成一個整體來處理。以下正則表達式可以匹配重復出現字符串“abc”一次或兩次的字符串。
此時,表達式將“abc”看成一個整體來進行重復匹配。
如以下正則表達式可以匹配簡單的IP地址:
(\d{1,3}){3}\d{1,3}2.3.3 反向引用
當一個正則表達式被分組之后,每一個組將自動被賦予一個組號,該組號可以代表該組的表達式。
其中,組號的編制規則為:從左到右、以分組的左括號“(”為標志,第一個分組的組號為1,第二個分組的組號為2,依此類推。
反向引用提供了查找重復字符組的簡便方法。它們可以被認為是再次匹配同一個字符串的快捷指令。
反向引用可以使用數字命名(即默認名稱)的組號,也可以使用指定命名的組號。具體說明如表所示。
| \數字 | 使用數字命名的反向引用 |
| \k<name> | 使用指定命名的反向引用 |
如:
\b(\w)\1\b只匹配含有兩個重復字符且長度為2的單詞
采用自定義分組名的方式,
如上邊的將\w命名為"Word的方法有兩種
上面的式子就可以等價于
\b(?<word>\w)\k<word>\b2.4 零寬斷言
零寬斷言的意思是(匹配寬度為零,滿足一定的條件/斷言) 我也不知道這個詞語是那個王八蛋發明的,簡直是太拗口了。
零寬斷言用于查找在某些內容(但并不包括這些內容)之前或之后的東西,也就是說它們像\b,^,$那樣用于指定一個位置,這個位置應該滿足一定的條件(即斷言),因此它們也被稱為零寬斷言。
斷言用來聲明一個應該為真的事實。正則表達式中只有當斷言為真時才會繼續進行匹配。
其中零寬斷言又分四種
先行斷言 也叫零寬度正預測先行斷言(?=表達式) 表示匹配表達式前面的位置
例如 [a-z]*(?=ing) 可以匹配cooking singing 中的cook與sing
注意:先行斷言的執行步驟是這樣的先從要匹配的字符串中的最右端找到第一個ing(也就是先行斷言中的表達式)然后 再匹配其前面的表達式,若無法匹配則繼續查找第二個ing 再匹配第二個 ing前面的字符串,若能匹配 則匹配
例如:.*(?=ing) 可以匹配cooking singing 中的cooking sing 而不是 cook
后發斷言 也叫零寬度正回顧后發斷言 (?<=表達式) 表示匹配表達式后面的位置
例如(?<=abc).* 可以匹配abcdefg中的defg
注意:后發斷言跟先行斷言恰恰相反 它的執行步驟是這樣的:先從要匹配的字符串中的最左端找到第一個abc(也就是先行斷言中的表達式)然后 再匹配其后面的表達式,若無法匹配則繼續查找第二個abc 再匹配第二個abc后面的字符串,若能匹配 則匹配
例如(?<=abc).* 可以匹配abcdefgabc中的defgabc 而不是abcdefg
負向零寬斷言
負向零寬斷言 (?!表達式) 也是匹配一個零寬度的位置,不過這個位置的“斷言”取表達式的反值,例如 (?!表達式) 表示 表達式 前面的位置,如果 表達式 不成立 ,匹配這個位置;如果 表達式 成立,則不匹配:同樣,負向零寬斷言也有“先行”和“后發”兩種,負向零寬后發斷言為 (?<!表達式)
負向零寬后發斷言(?<!表達式)
負向零寬先行斷言 (?!表達式)
負向零寬斷言要注意的跟正向的一樣
匹配HTML
匹配HTML標記
HTML一般由尖括號包圍,如<a>、<input>,可以用一下模式進行匹配。
<[a-zA-Z][^>]*>該正則表達式解釋如下。
- <匹配HTML標記的左尖括號。
- 字符類[a-zA?Z] , 可以匹配一個英文字母,它匹配HTML標記中除去左尖括號的第一個字符。
- 字符類[^>]可以匹配除右尖括號之外的任何字符。
- [^>]*可以匹配空字符串,或者由除右尖括號之外的任何字符組成的字符串。
-
匹配HTML標記的右尖括號。
匹配HTML標記之間的內容
(?<=<(?<tag>\w+)>).*(?=<\/\k<tag>>)以<a> dnskj<b>ssk</b></a>為例
- (?<tag>\w+):這是一個分組匹配的是 a
- <(?<tag>\w+)>:匹配<a>
- (?<=<(?<tag>\w+)>):其中?<=是零寬度正回顧后發言。匹配其之后的字符。相當于把<a>去掉
- .*:匹配dnskj<b>ssk</b>
- \k<tag>:反引用,相當于a
- <\/\k<tag>> :匹配</a>
- (?=<\/\k<tag>>):?=是零寬度正預測先行發言,匹配其之前的字符,相當于把</a>去掉。
總結
以上是生活随笔為你收集整理的正则表达式笔记(一)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 谭浩强课后题之----水仙花数
- 下一篇: 算法题目中元素为二元(坐标)的几种解决方