學如逆水行舟,不進則退
什么是正則表達式
Regular Expression使用單個字符串來描述、匹配一系列符合某種規則的字符串。
簡單來說就是按照某種規則去匹配符合條件的字符串。
舉個栗子,我們要查找當前目錄的所有txt文件,就可以通過正則表達式來完成:
find ./ -name *.txt
當然這只是個很簡單的例子。
其實真正用到的有可能是這個樣子的:
^([a-zA-Z0-9_-])+@([a-zA-Z0-9_-])+((\.[a-zA-Z0-9_-]{2,3}){1,2})$
這是驗證郵箱的一個規則,所以想要在實際工程中運用,還需要深入學習學習。
而且有大神寫出了一個正則表達式的可視化工具,可以方便的查看你的正則表達式的意思:
點擊鏈接:Regexper
還有一款工具可以實時顯示的也很不錯:
點擊鏈接:Regulex
通配符
下面我們開始學習一些通配符,看看他們都是什么意思。
\b ? WordBoundary,單詞的邊界;
\d ? Digit,數字;
. ??? AnyChar,任意字符;
^ ?? Start開頭;
$ ?? End結尾;
{4}?? 表示重復4次;
[/-] ? / 或者 - 其中一個,中括號表示或;
()?? 表示分組;
$1?? 表示提取前面括號里的分組內容,按順序排列$1 $2 $3……
例如:
^\d{4}[/-]\d{2}[/-]\d{2}$
匹配的就是像2017/01/07或者2017-01-07這樣的時間格式。
RegExp對象
JavaScript中通過內置對象RegExp來支持正則表達式。
而實例化RegExp對象有兩種方法:
- 字面量
- 構造函數
第一種方法:
var reg=/\bis\b/g;
"He is a boy,this is a dog.".replace(reg,"IS")
//先聲明了一個變量存儲表達式,然后替換字符串里所有的is為IS
//表達式中的g表示global全局
第二種方法:
var reg = new RegExp("\\bis\\b","g");
"He is a boy,this is a dog.".replace(reg,"IS")
//在js中使用\需要轉義,所以再加一個\;
修飾符
- g :global全文搜索,不加的話默認匹配第一個;
- i :ignore case 忽略大小寫,默認大小寫敏感;
- m :multiple lines多行搜索;
元字符
元字符是在正則表達式中有特殊含義的非字母字符。
* + ? $ ^ . | \ () [] {}
字符 | 含義 |
---|---|
\t | 水平制表符 |
\v | 垂直制表符 |
\n | 換行符 |
\r | 回車符 |
\0 | 空字符 |
\f | 換頁符 |
\cX | 與X對應的控制符(ctrl+X) |
字符類
我們可以用[]來構建一個簡單的類,所謂類就是符合某種規則的一類字符,而不是特指的單個字符;
例如:
"a1b2c3d4".replace(/[abc]/g,"x")
就會得到:"x1x2x3d4"
字符類取反
我們可以使用元字符^創建反向類/負向類;
反向類表示不屬于某類的內容;
比如[^abc]表示不是a或b或c的內容;
例如:
"a1b2c3d4".replace(/[^abc]/g,"x")
結果是axbxcxxx
范圍類
正則表達式還提供范圍類;
我們可以使用[a-z]來表示從a到z的任意字符;
在[]組成的類內部還可以連寫像這樣[a-zA-Z0-9]
舉個幾栗子:
"a1b2c3d4xYz".replace(/[a-z]/g,"x")
結果是x1x2x3x4xYx
"a1b2c3d4XYZ".replace(/[a-zA-Z]/g,"x")
結果是x1x2x3x4xxx
"2017-01-07".replace(/[0-9]/g,"x")
結果是xxxx-xx-xx
"2017-01-07".replace(/[0-9-]/g,"x")
結果是xxxxxxxxxx
預定義類
正則表達式還提供一些預定義類來匹配常見的字符類
字符 | 等價類 | 含義 |
---|---|---|
. | [^\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] | 非單詞字符 |
例如:匹配一個 “ab+數字+任意字符” 的字符串
只需要這樣:ab\d.
就可以解決了。
當然還有邊界字符:
字符 | 含義 |
---|---|
^ | 以×××開始 |
$ | 以×××結束 |
\b | 單詞邊界 |
\B | 非單詞邊界 |
量詞
字符 | 含義 |
---|---|
? | 出現零次或一次(最多一次) |
+ | 出現一次或多次(最少一次) |
* | 出現零次或多次(任意次) |
{n} | 出現n次 |
{n,m} | 出現n到m次 |
{n,} | 最少出現n次 |
舉個栗子:
\d{20}\w?\d\w+\d*\d{3}\w{3,5}\d{3,}
什么意思呢,來看圖:
正則表達式的貪婪和非貪婪模式
貪婪模式顧名思義就是盡可能多的匹配,知道匹配失敗為止。
例如:
"12345678".replace(/\d{3,6}/g,"x")
結果是:"x78"
非貪婪模式就是盡可能少的匹配,一旦匹配成功就不再進行匹配。
怎么使用非貪婪模式呢?很簡單,在量詞后面加上“?”就可以了。
例如:
"12345678".replace(/\d{3,6}?/g,"x")
結果是:"xx78"
分組
我們使用()可以到達分組的效果,使量詞可以作用于整個分組而不是緊挨的單個字符。
例如:
"a1b2c3d4".replace(/[a-z]\d{3}/g,"x")
結果是:"xd4"
或
使用|
可以達到或的效果
反向引用
如果我們想把2017-01-07這樣一個字符串替換為01/07/2017這樣。
可以用$和()來實現
"2017-01-07".replace(/(\d{4})-(\d{2})-(\d{2})/g,"$2/$3/$1")
結果是:"01/07/2017"
分組默認是自動排序的,如果不想被分組呢,只需要在括號里面加上“?:”就可以忽略該分組了:
前瞻
正則表達式從文本的頭部向尾部進行解析,文本的尾部方向,稱為“前”。
前瞻就是在正則表達式匹配到規則的時候,向前檢查是否符合斷言,后瞻方向相反。
需要注意的是Javascript并不支持后瞻。
符合和不符合特定斷言分別稱為正向/肯定匹配和負向/否定匹配。
名稱 | 正則 |
---|---|
正向前瞻 | exp(?=assert) |
負向前瞻 | exp(?!assert) |
再來個栗子:
"a2*34v8".replace(/\w(?=\d)/g,"x")
結果:"x2*x4x8"
"a2*34v8".replace(/\w(?!\d)/g,"x")
結果:"ax*3xxx"