JavaScript || 正則表達式
1 為什么要用正則表達式?
學習之前,多想想為什么要使用正則表達式,有助于理解。
正則表達式 regular expression 使用單個字符串來 描述某個句法規則 ,計算機根據規則去匹配字符串中的內容。
-
正則表達式的性能高于常規字符串操作(省略循環、遍歷等操作)
-
正則表達式僅用于字符串的操作
2 常規字符串操作與正則表達式的比較
要提取出字符串中 'ashx521dasbx34sasdz275dasdzxd897' 中連續的數字,并將結果保存在數組中 ['521', '34', '275', '897']
-
傳統字符串操作:需要遍歷整個字符串,判斷每個字符是否在 '0'-'9' 之間再進行相應的操作
/**
- 使用一個暫時變量tmp保存連續為數值時的字符串,間斷后再統一加入數組內;
- 可能會出現最后一位是數字的情況,所以使用i<=str.length多走一次循環的else路徑,將最后一組數組加入數組
*/ function findNum_two(str) { var arr = []; var tmp = ''; // 遍歷字符串,取出需要的數字 for(var i=0; i<=str.length; i++) {
if(str.charAt(i) <= '9' && str.charAt(i) >= '0') { tmp += str[i]; } else { if(tmp) { // 如果tmp不為空 arr.push(tmp); tmp = ''; } }
}
return arr; } console.log(findNum_two(str)); // [ '521', '34', '275', '897' ]</code></pre> </li>
-
使用正則表達式:只需使用字符串的 match() 方法去匹配指定的規則(正則表達式即可)
function findNum (str) { return str.match(/\d+/g); }
console.log(findNum(str)); // [ '521', '34', '275', '897' ]</code></pre> </li> </ol>
3 正則表達式寫法
-
字面量寫法: var re = /\d+/gi;
-
構造函數寫法: var re = new RegExp('\\d+', 'gi'); 注意兩個 \\ ,因為JavaScript中 \ 需要轉義
3.1 正則表達式中的轉義字符
轉義字符:單獨使用字母本身有意義;在前面加上 \ 后改變原有意義
3.2 量詞
用來描述相鄰的前面的單個字符匹配規則出現的次數
-
量詞使用 {a, b} 表示,其中 b 可以省略,意義不同
3.3 字符類
-
使用 [] 描述一類字符, 整體只代表一個字符 ,表示該字符在某個范圍內。
-
/a[0-9]c/ 匹配三位字符串,第一位是 a ,第三位是 c ,第二位是 '0'-'9' 之間的任何一位都可以匹配成功
-
[] 多種規則是 或 | 的關系: [0-9a-zA-Z] 等
整個字符類 [0-9a-zA-Z] 只代表一位字符
注意,字符類中的 ^ 表示非的意思,不在某個范圍內 : [^\d] 表示非數字的字符
3.4 修飾符
-
g -- global :全局匹配,找到所有的匹配項,不是在第一個匹配后停止
-
i -- ignored :忽略大小寫
-
m :多行,將開始字符 ^ 和結束字符 $ 視為在多行上工作(每匹配一行的開始和結束以 \n 和 \r 分割)
-
u :將模式視為Unicode序列點的序列
3.5 匹配子項
對于復雜的正則表達式,可以使用 () 將其拆分為多個部分, 在 replace(re, fn) 回調函數中可以簡化匹配內容的操作
var re = /(\d+)(\w)(\S)/;
fn($0, $1, $2 ...)
-
$0 代表正則表達式本身匹配到的內容: (\d+)(\w)(\S)
-
$1 代表正則表達式的第一個匹配子項: (\d+)
-
$2 代表正則表達式第二個匹配子項: (\w)
-
...
3.6 重復子項
主要用于匹配字符串中重復的字符
-
var re = /(a)(b)(c)\1/; : \1 表示重復的第一個子項 (b) ,第4個位置的字符與第1個位置的字符相同
-
var re = /(a)(b)(c)\2/; : \2 表示重復的第二個子項 (b) ,第4個位置的字符與第2個位置的字符相同
-
var re = /(a)(b)(c)\3/; : \3 表示重復的第三個子項 (c) ,第4個位置的字符與第3個位置的字符相同
-
...
3.7 邏輯或 |
-
使用 | 代表邏輯或, | 左右兩個操作數只要有一個滿足要求即可
3.8 開始、結束標記
-
不在 [] 中使用 ^ , ^ 表示以最近的匹配字符規則開始整個匹配;
-
$ 表示以最近的匹配規則結束匹配
作用范圍只是 ^ 之后的第一個子項; $ 前的第一個子項
4 正則表達式的方法
主要有4中方法用于操作正則表達式:
-
match() 、 replace() 、 search() 是字符串的操作方法
-
test() 、 exec() 是正則表達式對象的操作方法
4.1 test()
根據 RegExp 去匹配字符串,如果匹配成功,返回 true ;匹配失敗返回 false 。 主要用于邏輯判斷
var str = "abxe2312dafxz"; var re = /\d+/;
re.test(str); // true</code></pre>
4.2 search()
根據 RegExp 去匹配字符串,返回第一個匹配成功字符串的首字符的索引;匹配失敗返回 -1 。 用于查找字符的索引,類似字符串的 indexOf() 方法
-
str.search(re)
4.3 match()
根據 RegExp 去匹配字符串,如果匹配成功,將匹配的結果保存在數組中返回;匹配失敗返回 null 。 默認第一次匹配后便停止繼續匹配,使用修飾符 g 進行全局匹配
-
str.match(re)
4.4 replace(re, newstr) 方法
根據 RegExp 去匹配字符串,如果匹配成功,將匹配的字符串更換為新的字符串 newstr 。
var str = 'a23gb'; var re = /\d+/;
str.replace(re, "xy"); // 'axygb'</code></pre>
replace() 方法的第二個參數可以是回調函數,其參數是每次匹配成功獲取的字符串。每次匹配成功都會執行一次回調函數
5 實踐
5.1 找到一個字符串中出現次數最多的字符及其出現的次數
var str = '1231asdaegj71836178asdhasssasalsdhdzxbczaslazxcnnffajshdhgagsgdssssasdzzxda';
var str = str.split('').sort().join(''); // 按順序的字符序列
var re = /(\w)\1+/g;
var length = 0; var val = ''; // 保存出現次數最多的字符
// $0代表每次匹配到的字符,$1代表第一個正則表達式子項(\w) str.replace(re, function ($0, $1) { // 可以將匹配的字符當做變量操作 if($0.length > length) { length = $0.length; val = $1; // $1代表每次匹配的字符 } }); console.log(length); console.log(val);</code></pre>
5.2 去掉字符串前后的空格
-
var re = /^\s+|\s+$/g; ,使用字符串應用正則即可: str.replace(re, '')
5.3 常用正則匹配規則
-
QQ號: var re = /^[1-9]\d{4,11}$/; :第一位是1-9中的數字,最后也是數字,總共5-12位
-
中文匹配: var re = /[\u4e00-\u9fa5]/; :使用Unicode編碼進行匹配
-
email : var re = /\w+@[a-z0-9]+(\.[a-z]+){1,3}/; :可能出現 .com.cn.net
-
身份證: var re = /[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x/i;
-
郵編: var re = /[1-9]\d{5}/;
5.3 將常用正則表達式封裝在一個對象中便于使用
var re = { email: /\w+@[a-z0-9]+(\.[a-z]+){1,3}/, chinese: /[\u4e00-\u9fa5]/, qq: /^[1-9]\d{4,11}$/, id: /[1-9]\d{14}|[1-9]\d{17}|[1-9]\d{16}x/i, trim: /^\s+|\s+$/ }
來自:https://segmentfault.com/a/1190000008729041