js正則表達式

@(javascript)[js正則表達式]javascript

[toc]html

js正則表達式

正則表達式一直是一個使人頭疼但卻又是十分重要的一個東西。熟練的使用正則表達式可讓你的工做事半功倍。接下來,一塊兒來看看正則表達式是什麼吧!java

正則表達式概念

正則表達式,又稱規則表達式。(英語:Regular Expression,在代碼中常簡寫爲regex、regexp或RE),計算機科學的一個概念。正則表一般被用來檢索、替換那些符合某個模式(規則)的文本。正則表達式

正則表達式的基本語法

var reg = / pattern / flags;
複製代碼

就像上面的,正則表達式是由兩個/符號包裹起來的,兩個/裏面的(上面的pattern)就是須要的任何簡單或者是複雜的正則表達式。而在第二個/後面是一個或者是多個標誌(flags),用來標明正則表達式的行爲。 flags有如下五種行爲:數組

  • g:表示全局(global)模式,即在匹配到第一個後繼續匹配
  • i:忽略(ignore)大小寫
  • m:即是多行(multiline)模式,即到達一行時繼續查找下一行
  • y:(ES6新增的粘連修飾符)
  • u:(ES6新增)

正則的規則分類

下面根據JavaScript正則表達式的速查表中的分類來對每一下進行一個說明。bash

正則表達式基礎

基礎裏面呢主要有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次或者屢次

這裏涉及到一個貪婪匹配非貪婪匹配貪婪匹配指的是使用以上量詞的時候會按照最大次數進行匹配。 非貪婪匹配則是按最小次數進行匹配。ui

使用非貪婪匹配只需在兩次後面加上一個?spa

// `*`的使用
// 非全局匹配。
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"]
複製代碼

分析:

  1. 捕獲組就是在匹配 ()外面的字符以後在匹配 () 裏面的。結果中的 "abcd1234"
  2. 捕獲組裏面還有捕獲組會先忽略裏面的捕獲組匹配在一次匹配裏面的捕獲組。結果中的"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"]
複製代碼

上面的例子中,reg1reg2 僅僅有一點不一樣。可是匹配後的東西是不一樣的。簡單地說,就是,使用 \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.indexres.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/

更多的匹配可查閱:最全的經常使用正則表達式大全

以上就是關於正則的一些使用概念以及使用方法。若是想要熟練的使用正則去匹配或者是修改字符串。仍是須要不斷的練習纔是。

相關文章
相關標籤/搜索