最近在學PHP,js時需要用到正則表達式,盡管在學Python時學了一些但是不夠系統。每次看到繁瑣的正則,就淺嘗輒止。在此做一個總結,以便自己后續的學習。
什么是正則表達式
正則表達式(regular expression)
描述了一種字符串匹配的模式,按照某種規則去匹配符合條件的字符串。
為什么使用正則表達式?
通過使用正則表達式,可以:
- 測試字符串內的模式。
例如,可以測試輸入字符串,以查看字符串內是否出現電話號碼模式或信用卡號碼模式。這稱為數據驗證。
- 查找,替換文本。
可以使用正則表達式來識別文檔中的特定文本,完全刪除該文本或者用其他文本替換它。
- 基于模式匹配從字符串中提取子字符串。
可以查找文檔內或輸入域內特定的文本。
正則表達式語法
正則表達式由兩種基本字符類型組成:
原義文本字符
元字符
元字符是正則表達式中有特殊含義的非字母字符。
普通字符
普通字符包括沒有顯式指定為元字符的所有可打印和不可打印字符。這包括所有大寫和小寫字母、所有數字、所有標點符號和一些其他符號。
非打印字符
字符 | 描述 |
---|---|
\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。 |
特別字符
所謂特殊字符,就是一些有特殊含義的字符,如上面說的"*.txt"中的*,簡單的說就是表示任何字符串的意思。如果要查找文件名中有*的文件,則需要對*進行轉義,即在其前加一個\。ls *.txt。正則表達式有以下特殊字符。
字符 | 描述 |
---|---|
$ | 匹配輸入字符串的結尾位置。如果設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符本身,請使用 $。 |
( ) | 標記一個子表達式的開始和結束位置。子表達式可以獲取供以后使用。要匹配這些字符,請使用 \( 和 \) 。 |
* | 匹配前面的子表達式零次或多次。要匹配 * 字符,請使用 \* 。 |
+ | 匹配前面的子表達式一次或多次。要匹配 + 字符,請使用 \+ 。 |
. | 匹配除換行符 \n之外的任何單 字符。要匹配 .,請使用 \。 |
[ | 標記一個中括號表達式的開始。要匹配 [,請使用 \[ 。 |
? | 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用 ?。 |
\ | 將下一個字符標記為或特殊字符、或原義字符、或向后引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\ ' 匹配 "",而 '\( ' 則匹配 "( "。 |
^ | 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符本身,請使用 \^ 。 |
{ | 標記限定符表達式的開始。要匹配 {,請使用 \{ 。 |
丨 | 指明兩項之間的一個選擇。要匹配 丨,請使用 \丨 。 |
在表格里輸入
|
嘗試過\|
,但可以用中文gun來假裝一下哈哈哈哈
限定符
限定符用來指定正則表達式的一個給定組件必須要出現多少次才能滿足匹配。有*或+或?或{n}或{n,}或{n,m}共6種。
*、+和?限定符都是貪婪的,因為它們會盡可能多的匹配文字,只有在它們的后面加上一個?就可以實現非貪婪或最小匹配。
字符 | 描述 |
---|---|
* | 匹配前面的子表達式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。* 等價于{0,}。 |
+ | 匹配前面的子表達式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等價于 {1,}。 |
? | 匹配前面的子表達式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等價于 {0,1}。 |
{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?'。請注意在逗號和兩個數之間不能有空格。 |
定位符
用來描述字符串或單詞的邊界。
^和$分別指字符串的開始與結束。
\b描述單詞的前或后邊界。
\B表示非單詞邊界。
注:不能對定位符使用限定符。
操作符優先級
轉義符 > 圓括號和方括號 > 限定符 > 位置和順序 > “或”操作
一些匹配規則
我們可以用[]
來構建一個簡單的類。所謂的類就是指符合某些特性的對象,即匹配方括號內任意一個都可。 當在一組方括號里使用^是,它表示“非”或“排除”的意思,常常用來剔除某個字符。即反向類。另外,還給我們提供了范圍類,連字號可以表示一個字符的范圍,[a-z]即匹配所有的小寫字母。
下面舉一些例子:
[a-z] //匹配所有的小寫字母
[A-Z] //匹配所有的大寫字母
[a-zA-Z] //匹配所有的字母
[0-9] //匹配所有的數字
[0-9.-] //匹配所有的數字,句號和減號
[ \f\r\t\n] //匹配所有的白字符
\d 匹配一個數字字符。等價于 [0-9]。
\D 匹配一個非數字字符。等價于 [^0-9]。
另外,特殊字符"."等價[^\r\n]
在正規表達式中用來表示除了回車換行之外的所有字符。
"\d"等價[0-9]
在正規表達式中用來表示數字字符。
"\D"等價[^0-9]
在正規表達式中用來表示非數字字符。
"\s"等價[\t\n\x0B\f\r]
在正規表達式中用來表示空白符。
"\S"等價[^\t\n\x0B\f\r]
在正規表達式中用來表示非空白符。
"\w"等價[a-zA-Z_0-9]
在正規表達式中用來表示數字字母下劃線。
"\W"等價[^a-zA-Z_0-9]
在正規表達式中用來表示非單詞字符。
量詞
到現在為止,你已經知道如何去匹配一個字母或數字,但更多的情況下,可能要匹配一個單詞或一組數字。一個單詞有若干個字母組成,一組數字有若干個單數組成。跟在字符或字符簇后面的花括號({})用來確定前面的內容的重復出現的次數。
如:
^a{4}$ aaaa
^a{2,}$ 包含多于兩個a的字符串
^a{1,3}$ a,aa或aaa
這些例子描述了花括號的三種不同的用法。一個數字,{x}的意思是“前面的字符或字符簇只出現x次”;一個數字加逗號,{x,}的意思是“前面的內容出現x或更多的次數”,之前所說的+
即表示比配一次或多次,等同于{1,};兩個用逗號分隔的數字,{x,y}表示“前面的內容至少出現x次,但不超過y次”。
^[a-zA-Z0-9_]{1,}$ //所有包含一個以上的字母、數字或下劃線的字符串
^[0-9]{1,}$ //所有的正數
^-{0,1}[0-9]{1,}$ //所有的整數
^-{0,1}[0-9]{0,}.{0,1}[0-9]{0,}$ //所有的小數
另外,?
字符表示出現零次或一次(最多出現一次);
+
字符表示出現一次或多次(至少出現一次);
*
字符表示出現零次或多次(任意次);
分組
在某些情況,如果想匹配apple3次,估計大家會這樣寫:apple{3}
可是查找結果卻是:
因此,我們需要用到()
分組。應該寫成(apple){3}
選擇
用圓括號將所有選擇項括起來,相鄰的選擇項之間用|分隔。但用圓括號會有一個副作用,是相關的匹配會被緩存,此時可用?:
放在第一個選項前來消除這種副作用。
反向引用
對一個正則表達式模式或部分模式兩邊添加圓括號將導致相關匹配存儲到一個臨時緩沖區中,所捕獲的每個子匹配都按照在正則表達式模式中從左至右所遇到的內容存儲。存儲子匹配的緩沖區編號從 1 開始,連續編號直至最大 99 個子表達式。每個緩沖區都可以使用 '\n' 訪問,其中 n 為一個標識特定緩沖區的一位或兩位十進制數。
可以在分組內加上非捕獲元字符 '?:', '?=', or '?!' 來忽略對相關匹配的保存。
前瞻
正則表達式從文本頭部向尾部開始解析,文本尾部方向稱為前
。
前瞻就是在正則表達式匹配到規則的時候,向前檢查是否符合斷言,后顧則相反。正向前瞻和負向前瞻就是判斷一個正則之后還沒有完,還需要在符合一個條件。
符合和不符合特定斷言稱之為肯定/正向匹配和否定/反向匹配。
正向前瞻 exp(?=assert)
反向前瞻 exp(?!assert)
正向后顧 exp(?<=assert)
反向后顧 exp(?<!assert)
(js不支持后顧)
exp為原正則部分,assert部分即斷言部分也是正則表達式,?=
和?!
,前者為正向前瞻,在任何開始匹配圓括號內的正則表達式模式的位置來匹配搜索字符串,后者為負向前瞻,在任何開始不匹配該正則表達式模式的位置來匹配搜索字符串。
javascript 中正則表達式的應用
js中通過內置對象REGEXP支持正則表達式。
有兩種方法實例化RegExp對象:
1.字面量 var reg = / \bis\b /g;
2.構造函數 var reg = new RegExp ('\bis\b','g');/*在Js中\也是特殊字符所以需要轉義,第一個是正則表達式文本,第二個字符串是標志位,g,全局匹配*/
javascript中正則表達式對象的屬性
g:global 全局匹配,不添加,匹配到第一個為止
i:ignore case 不分大小寫
m: multiple lines 多行搜索,使^變為新的行首
lastIndex:是當前表達式匹配內容的最后一個字符的下一個位置
source:正則表達式的文本字符串
javascript中正則對象本身的方法
RegExp.prototype.test(str)
作用:用于測試字符串參數中是否存在匹配正則表達式模式的字符串
符合返回true
,否則返回false
調用實例:
var reg = / \bis\b /g;
reg.test(str);
但當使用全局g屬性標識時,會修改lastIndex值,在匹配到最后一項之后會重置為0,因此會出現結果為反復的循環true、false,出現結果不穩定
其實test的本意,其實就是測試能否匹配上。
RegExp.prototype.exec(str)
作用:使用正則表達式模式對字符串執行搜索,并將更新全局RegExp對象的屬性以反映匹配結果。
如果沒有匹配到的文本則返回null,否則返回一個結果數組。
此數組有兩個屬性,
1.index:聲明匹配文本的第一個字符的位置
2.input:存放被檢索的字符串string
在非全局調用時,返回數組:
第一個元素是與正則表達式相匹配的文本
第二個元素是與RegExpObject的第一個子表達式相匹配到的文本
第三個元素是與RegExpObject的第二個子表達式相匹配到的文本,以此類推
javascript中字符串的方法
String.prototype.search(reg)
作用:用于檢索字符串中指定的子字符串,或檢索與正則表達式相匹配的子字符串。
方法返回第一個匹配結果 index,查找不到返回-1
不執行全局匹配,忽略g,總是從字符串的開始進行搜索。
String.prototype.match(reg)
作用:用于檢索字符串,以找到一個或多個與regxp匹配的文本
regxp是否具有標志位g對結果影響很大
在非全局調用時,返回數組,沒有匹配到的文本則返回null
返回數組第一個元素存放的是匹配文本,而其余的元素存放的是與正則表達式的子表達式匹配的文本
除了常規的數組元素之外,返回的數組還含有2個對象屬性
1.index:聲明匹配文本的第一個字符的位置
2.input:聲明對stringObject的引用
而在全局調用時,返回的數組存放的是字符串中所有的匹配子串,而且也沒有index和input屬性,就告訴你匹配結果。
String.prototype.split(reg)
作用:我們經常用split來把字符串分割為字符數組,而在一些復雜的情況下我們可以用正則表達式來分割。
String.prototype.replace(reg)
作用:替換內容,三種方法。
replace(str,replaceStr)
replace(reg,replaceStr)
replace(reg,function) 如將a1b2c3替換為a2b3c4
function(match,group,index,origin)參數含義
function會在每次匹配替換時調用,有4個參數
1.匹配字符串
2.正則表達式分組內容,沒有分組則沒有參數
3.匹配項在字符串中的index
4.原字符串
正則表達式測試工具:https://regexper.com