@(javascript)[js正則表達式]
[toc]
JS正則表達式
正則表達式一直是一個令人頭疼但卻又是十分重要的一個東西。熟練的使用正則表達式可以讓你的工作事半功倍。接下來,一起來看看正則表達式是什么吧!
正則表達式概念
正則表達式,又稱規則表達式。(英語:Regular Expression,在代碼中常簡寫為regex、regexp或RE),計算機科學的一個概念。正則表通常被用來檢索、替換那些符合某個模式(規則)的文本。
正則表達式的基本語法
var reg = / pattern / flags;
就像上面的,正則表達式是由兩個/
符號包裹起來的,兩個/
里面的(上面的pattern)就是需要的任何簡單或者是復雜的正則表達式。而在第二個/
后面是一個或者是多個標志(flags),用來標明正則表達式的行為。
flags有以下五種行為:
- g:表示全局(global)模式,即在匹配到第一個后繼續匹配
- i:忽略(ignore)大小寫
- m:便是多行(multiline)模式,即到達一行時繼續查找下一行
- y:(ES6新增的粘連修飾符)
- u:(ES6新增)
正則的規則分類
下面根據JavaScript正則表達式的速查表中的分類來對每一下進行一個說明。
正則表達式基礎
基礎里面呢主要有6
需要記憶的東西,分別是:
-
.
:匹配除了換行以外其他所有字符 -
a
:匹配字符a
,衍生為匹配單個字母 -
ab
:匹配字符串ab
,衍生為匹配字符串 -
a|b
:匹配a或者b
,就是或者的意思 -
a*
:匹配一次或者是多次a
-
\
:轉義符號,轉義一個特殊的字符
// `.`的使用
var reg = /./g;
var text = "abcdefg";
var res = text.match(reg);
console.log(res); // (7) ["a", "b", "c", "d", "e", "f", "g"]
// `a`的使用
var reg = /A/gi; // 全局匹配。忽略大小寫
var text = "abcdefg";
var res = text.match(reg);
console.log(res); // (7) ["a"]
// `ab`的使用
var reg = /AbCdef/gi; // 全局匹配。忽略大小寫
var text = "abcdefg";
var res = text.match(reg);
console.log(res); // (7) ["abcdef"]
// `a|b`的使用 一
var reg = /a|b|c|d/; // 非全局匹配。
var text = "abcdefg";
var res = text.match(reg);
console.log(res); // ["a", index: 0, input: "abcdefg"]
// `a|b`的使用 二
var reg = /a|b|c|d/g; // 全局匹配。
var text = "abcdefg";
var res = text.match(reg);
console.log(res); // (4) ["a", "b", "c", "d"]。使用全局匹配。會在匹配對后繼續匹配
// `a*`的使用
var reg = /a*/;
var text = "abcdcba";
var res = text.match(reg);
console.log(res); // ["a", index: 0, input: "abcdcba"]
// `a*`的使用
var reg = /a*/g; // 全局匹配。
var text = "abcdcba";
var res = text.match(reg);
console.log(res); // (8) ["a", "", "", "", "", "", "a", ""]。使用全局匹配會把之后沒有匹配到的轉化為空字符串
// `\`的使用 回到第一個 . 的使用那里。如果我把 . 前面加一個 \ 符號,那么這個點就是一個普通的點了
var reg = /\./g; // 全局匹配。
var text = "abcdefg";
var res = text.match(reg);
console.log(res); // null
JavaScript中需要使用 \
的特殊符號有:(
)
[
]
{
}
.
|
+
*
?
\
^
$
以及 空白
。
正則表達式字符類
-
[ab-d]
:a,b,c,d四個字符中的一個,衍生為使用[]
,那就是匹配其中的一個 -
[^ab-d]
:除了a,b,c,d四個字符其他的任意字符,衍生為使用[^]
可以排除[]里面的東西 -
[\b]
:退格字符,了解 -
\d
:一個0-9的數字 -
\D
:一個非數字 -
\s
:一個空白字符 -
\S
:一個非空白字符 -
\w
:匹配一個字母,數字或者是下劃線 -
\W
:匹配一個除字母,數字,下劃線之外的任意字符
// `[a-z]`的使用
var reg = /[a-z]/g; // 全局匹配。匹配 a-z 的任意一個,因為是全局匹配。所以會一直找。但是不會有 1234
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // (4) ["a", "b", "c", "d"]
// `[a-z]`的使用
var reg = /[^a-z]/g; // 全局匹配。匹配 除了 a-z 的任意一個。所以是 1 2 3 4。因為是全局匹配。所以會一直找
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // (4) ["1", "2", "3", "4"]
// `[\b]`的使用
var reg = /[\b]/g; // 全局匹配。匹配 \b,當然也可以匹配其他的特殊轉義字符,見 正則表達式特殊字符
var text = "abcd\b1234";
var res = text.match(reg);
console.log(res); // (4) ["1", "2", "3", "4"]
// `\d`,`\D`,`\s`,`\S`,`\w`,`\W`的使用
var reg = /\D\d/g; // 全局匹配。匹配一個非數字與一個數字。兩者緊靠在一起 注意順序
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // ["d1"]
// 如果是下面的一個,則匹配 null
var reg = /\D\d/g; // 全局匹配。匹配一個數字與一個非數字。兩者緊靠在一起 注意順序
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // null
// 匹配一個
var reg = /\D\s\w\d/g; // 全局匹配。注意順序 注意大小寫
var text1 = "abcd1234";
var text2 = "abcd _1234";
var res1 = text1.match(reg);
var res2 = text2.match(reg);
console.log(res1); // null
console.log(res2); // ["d _1"]
正則表達式量詞
-
*
:匹配0次
或者多次
。等價于{0,}
-
+
:匹配一次
或者多次
。等價于{1,}
-
?
:匹配0次
或者一次
。等價于{0,1}
-
{2}
:只匹配2
次 -
{2, 5}
:匹配2-5
次 -
{2,}
:匹配2次
或者多次
這里涉及到一個貪婪匹配
與非貪婪匹配
。
貪婪匹配
指的是使用以上量詞的時候會按照最大次數進行匹配。
非貪婪匹配
則是按最小次數進行匹配。
使用非貪婪匹配只需在兩次后面加上一個?
// `*`的使用
// 非全局匹配。
var reg = /[a-z]*/; // 匹配 a-z 的0個或者多個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // ["abcd", index: 0, input: "abcd1234"]
// 全局匹配。
var reg = /[a-z]*/g; // 匹配 a-z 的0個或者多個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // (6) ["abcd", "", "", "", "", ""]。當匹配為 0 個的時候,會變成空字符串。對比 + 號
// `+`的使用
// 非全局匹配。
var reg = /[a-z]+/; // 匹配 a-z 的0個或者多個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // ["abcd", index: 0, input: "abcd1234"]
// 全局匹配。
var reg = /[a-z]+/g; // 匹配 a-z 的0個或者多
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // ["abcd"]。因為至少匹配一個,所以不會有空字符串。對比 * 號
// `?`的使用
// 非全局匹配。
var reg = /[a-z]?/; // 匹配 a-z 的0個或者一個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // ["a", index: 0, input: "abcd1234"]。匹配到一個就停下來
// 全局匹配。
var reg = /[a-z]?/g; // 匹配 a-z 的0個或者一個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // ["a", "b", "c", "d", "", "", "", "", ""]。abcd匹配到了。1234則是空字符串。
以上說的都屬于貪婪匹配
。都是按最多個匹配的。如果是非貪婪匹配
。則是按照最少的次數匹配。
// `*`的使用
// 非全局匹配。貪婪匹配
var reg = /[a-z]*/; // 匹配 a-z 的0個或者多個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // ["abcd", index: 0, input: "abcd1234"]
// 全局匹配。貪婪匹配
var reg = /[a-z]*/g; // 匹配 a-z 的0個或者多個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // (6) ["abcd", "", "", "", "", ""]。當匹配為 0 個的時候,會變成空字符串。對比 + 號
// 非全局匹配。非貪婪匹配
var reg = /[a-z]*?/; // 匹配 a-z 的0個或者多個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // ["", index: 0, input: "abcd1234"]
// 全局匹配。非貪婪匹配
var reg = /[a-z]*?/g; // 匹配 a-z 的0個或者多個
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // (9) ["", "", "", "", "", "", "", "", ""]
以上就是貪婪匹配
與非貪婪匹配
的區別。不過不管是如何。在匹配是0
次的時候。空字符串的個數
總是匹配不成功部分的字符串的長度+1
正則表達式捕獲組與非捕獲組
-
(...)
:捕獲組 -
(?...)
:非捕獲組 -
\Y
:匹配第Y個被捕獲的組(也稱反向引用
)。其中Y
是一個數字,這個數組取值范圍是*
,即{0,}
。但是建議反向引用
不要索引大于9的捕獲性分組。
捕獲組
var reg = /ab(cd(1234))/;
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // (3) ["abcd1234", "cd1234", "1234", index: 0, input: "abcd1234"]
分析:
- 捕獲組就是在匹配
()
外面的字符之后在匹配()
里面的。結果中的 "abcd1234" - 捕獲組里面還有捕獲組會先忽略里面的捕獲組匹配在一次匹配里面的捕獲組。結果中的
"cd1234"
與"1234"
非捕獲組
var reg = /ab(?:cd(1234))/;
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // (3) ["abcd1234", "1234", index: 0, input: "abcd1234"]
分析:非捕獲組就是不捕獲,就行上面的結果中沒有了"cd1234"
那么捕獲與非捕獲有什么區別呢? 記得看寵物小精靈的時候小智看見新的小精靈扔球抓小精靈的時候就屬于一個捕獲,如果看見不扔球那就是不捕獲。那捕獲和不捕獲有什么區別呢?就行抓小精靈一樣,抓住了之后就可以用了嘛!所以被捕獲的東西之后是可以使用的。那么怎么使用呢? 問得好。這時候就需要使用到\Y
了。
var reg1 = /(a)/;
var reg2 = /(a)\1/; // 相當于是 /(a)a/
var text1 = "aabb1234";
var text2 = "aabb1234";
var res1 = text1.match(reg1);
var res2 = text2.match(reg2);
console.log(res1); // ["a", "a", index: 0, input: "aabb1234"]
console.log(res2); // ["aa", "a", index: 0, input: "aabb1234"]
上面的例子中,reg1
與 reg2
僅僅有一點不同。但是匹配后的東西是不同的。簡單地說,就是,使用 \Y
后會賦值第Y個捕獲的組。以下代碼說明通過$Y
來接收相應的捕獲組。不能從0開始
\Y
var reg = /ab(cd(1234))/;
var text = "abcd1234";
var res = text.match(reg);
console.log(res); // (3) ["abcd1234", "cd1234", "1234", index: 0, input: "abcd1234"]
console.log(RegExp.$0); // undefined
console.log(RegExp.$1); // cd1234
console.log(RegExp.$2); // 1234
var res1 = text.replace(reg,"$1$2"); // 使用 $1 $2 取出捕獲組的內容
console.log(res1); // cd12341234
正則表達式斷言
-
^
:字符串的開始必須是 -
$
:字符串的結尾必須是 -
\b
:匹配文字(單詞)邊界 -
\B
:非文字(單詞)邊界 -
(?=...)
:積極的前瞻(也叫前瞻或者是順序肯定環視) -
(?!...)
:消極的前瞻(也加后瞻或者是順序否定環視)
^
,$
的使用
var reg = /^b.*\d$/; // 要求字符 b 開頭,中間 * 個任意字符(除換行符),必須以數字結束
var text1 = "abcd1234";
var text2 = "bcd";
var text3 = "bcd1234";
var res1 = text1.match(reg);
var res2 = text2.match(reg);
var res3 = text3.match(reg);
console.log(res1); // null
console.log(res2); // null
console.log(res3); // ["bcd1234", index: 0, input: "bcd1234"]
\b
,\B
的使用
var reg = /\bhi\b/; //
var text1 = "hi";
var text2 = "him";
var text3 = "history";
var res1 = text1.match(reg);
var res2 = text2.match(reg);
var res3 = text3.match(reg);
console.log(res1); // ["hi", index: 0, input: "hi"]
console.log(res2); // null
console.log(res3); // null
積極的前瞻 (?=...) 積極的前瞻 匹配后面是 ... 的位置,不捕獲匹配結果
var reg = /abcd(?=1234)/;
var text = "abcd1234";
var text1 = "abcdefg";
var res = text.match(reg);
var res1 = text1.match(reg);
console.log(res) // ["abcd", index: 0, input: "abcd1234"]
console.log(res1) // null
看上面的例子可以看出積極的前瞻匹配1234
前面的abcd
,不匹配def
前面的abcd
;而消極的前瞻恰恰相反,看下面的例子。
消極的前瞻 (?!...) 消極的前瞻 匹配后面不是 ... 的位置,不捕獲匹配結果
var reg = /abcd(?!=1234)/;
var text = "abcd1234";
var text1 = "abcdefg";
var res = text.match(reg);
var res1 = text1.match(reg);
console.log(res) // null
console.log(res1) // ["abcd", index: 0, input: "abcd1234"]
正則表達式特殊字符
-
\n
:換行符 -
\r
:回車符 -
\t
:制表符 -
\0
:空字符 -
\YYY
:8進制字符 -
\xYY
:十六進制字符 -
\uYYYY
:十六進制字符 -
\cY
:控制符
正則的特殊字符在實際中運用的比較少,具體的用法與之前講到的[\b]
類似。上面的兩個十六進制字符
中,\xYY
主要匹配數字字母等。而\uYYYY
則是為了匹配漢字以及以下特殊的符號。
正則表達式替換
正則表達式替換主要是替換一些字符。主要以下幾個,可是在replace
中使用。
-
$$
:插入$
-
$&
:插入整個匹配 - $`:插入匹配項前面的字符串
-
$'
:插入匹配項后面的字符串 -
$Y
:插入第Y個捕獲的組
var reg = /.{2}水(.)/;
var text = "君子之交淡如水,小人之交甘若醴";
var res = text.match(reg);
console.log(res); // (2) ["淡如水,", ",", index: 4, input: "君子之交淡如水,小人之交甘若醴"]
$$
:插入$
var reg = /.{2}水(.)/;
var text = "君子之交淡如水,小人之交甘若醴";
var newStr = text.replace(reg,"$$");
console.log(newStr); // 君子之交$小人之交甘若醴
$&
:插入整個匹配
var reg = /.{2}水(.)/;
var text = "君子之交淡如水,小人之交甘若醴";
var newStr = text.replace(reg,"$&");
console.log(newStr); // 君子之交淡如水,小人之交甘若醴
$`:插入匹配項前面的字符串
var reg = /.{2}水(.)/;
var text = "君子之交淡如水,小人之交甘若醴";
var newStr = text.replace(reg,"$`");
console.log(newStr); // 君子之交君子之交小人之交甘若醴
$'
:插入匹配項后面的字符串
var reg = /.{2}水(.)/;
var text = "君子之交淡如水,小人之交甘若醴";
var newStr = text.replace(reg,"$'");
console.log(newStr); // 君子之交小人之交甘若醴小人之交甘若醴
$Y
:插入第Y個捕獲的組
var reg = /.{2}水(.)/;
var text = "君子之交淡如水,小人之交甘若醴";
var newStr = text.replace(reg,"$1");
console.log(newStr); // 君子之交,小人之交甘若醴
正則表達式實例的方法
exec() 最主要的方法
此方法專門為捕獲組設計的。此方法接收一個參數,及需要測試的字符串
。返回數組或者是null。但返回的值包含兩個額外的屬性:
index
:匹配性在字符串中的位置
input
:應用正則的表達式
var reg = /你(我他(與她))/
var text = "你我他與她";
var res = reg.exec(text);
console.log(res); //(3) ["你我他與她", "我他與她", "與她", index: 0, input: "你我他與她"]
["你我他與她", "我他與她", "與她", index: 0, input: "你我他與她"]
的結果。使用res[下標]
可以查看具體的匹配下。從第二項開始才是捕獲項
。使用res.index
與res.input
查看起始位置與匹配的字符串。
exec()方法始終返回一項,如果設置了全局匹配g
,只會從上一次結束的敵法繼續查找,而不會返回多項。
var text = "bat, cat, fat";
var reg1 = /.at/;
var res = reg1.exec(text);
console.log(res.index); // 0
console.log(res[0]); // bat
var res = reg1.exec(text);
console.log(res.index); // 0
console.log(res[0]); // bat
var reg2 = /.at/g;
var res = reg2.exec(text);
console.log(res.index); // 0
console.log(res[0]); // bat
var res = reg2.exec(text);
console.log(res.index); // 5
console.log(res[0]); // cat
test()方法
接收一個字符串作為參數,返回:
true
:匹配
false
:不匹配
var text = "abcd1234";
var reg1 = /\D/g;
var reg2 = /\s/g;
var res1 = reg1.test(text);
console.log(res1); // true
var res2 = reg2.test(text);
console.log(res2); // false
關于使用RegExp構造函數
語法:var reg = new RegExp(參數1[,參數2])
;
var reg = new RegExp("\D","gi");
var text = "ABd1234";
var res = reg.exec(text);
console.log(res); // ["d", index: 2, input: "ABd1234"]
看上面的例子。兩個參數需要使用字符串
。
但是,上面的例子有一個問題。沒有按照我們所想的出現一個A
,而是一個d
。同時,我們忽略大小寫在看一下:
var reg = new RegExp("\D","g");
var text = "ABd1234";
var res = reg.exec(text);
console.log(res); // null
所以,使用構造函數還有一個需要注意的就是所有的元字符都需要雙重轉義
。將上面的代碼換為下面的看看
var reg = new RegExp("\\D","g");
var text = "ABd1234";
var res = reg.exec(text);
console.log(res); // ["A", index: 0, input: "ABd1234"]
注意上面的\\D
。這個才表示一個元字符。剛剛的就是一個\
一個D
。所以。在正則的構造函數中使用元字符
需要雙重轉義
。
附上幾個常用的正則匹配
電話號碼匹配:/^1[3-8]\d{9}$/
電子郵件:/[a-zA-z0-9_-]{6,12}@[a-zA-z0-9_-]+\.[a-zA-z0-9]+/
匹配特定了的郵件:/[a-zA-z0-9_-]{6,12}@(163|qq|gmail)\.com/
更多的匹配可查閱:最全的常用正則表達式大全
以上就是關于正則的一些使用概念以及使用方法。如果想要熟練的使用正則去匹配或者是修改字符串。還是需要不斷的練習才是。