看完你就會正則表達式了

出場

爲了匹配規定模式的文本
爲了守護世界的和平
咱們是穿梭在銀河的正則表達式
就是這樣~喵~html

好用的正則表達式可視化工具: https://regexper.com/git

語法

//字面量
var regExp1 = /pattern/flags;

//或用構造函數
var regExp2 = new RegExp(pattern[, flags]);

pattern:正則表達式的匹配模式
flags:可選,正則表達式的標識,也可選多個。g全局匹配,i忽略大小寫,m匹配多行github

一顆超簡單的栗子:正則表達式

var regExp = /abc/;
"abcdefg".replace(regExp, "WOW"); // "WOWdefg"

經常使用特殊字符

1.字符集合

字符 舉例 含義
[] [xyz] xyz中任意一個字符 等價於[x-z]
[^] [^xyz] 匹配任意不在xyz中的一個字符,等價於[^x-z] (注意與^x區分,後者表示匹配以x開頭的字符)
[-] [1-3] 匹配123中的任意一個字符,等價於[123]。注意:連字符只有出如今方括號中才表示連續的字符序列。

2.預約義模式

預約義模式就是某些經常使用模式的簡寫。數組

字符 含義
. 除\r和\n以外的任意字符,等價於[^\r\n]
\d 數字0-9,等價於[0-9]
\D 非數字字符,等價於[^0-9]
\w 字母數字下劃線,等價於[A-Za-z0-9_]
\W 非字母數字下劃線,等價於[^A-Za-z0-9_]
\s 空白符
\S 非空白符
\n 換行符

3.須要轉義的字符

正則模式中,須要用斜槓轉義的:數據結構

* + ? $ ^ . | \ ( ) { } [ ]

須要特別注意的是,若是使用RegExp方法生成正則對象,轉義須要使用兩個斜槓,由於字符串內部會先轉義一次。dom

4.邊界

字符 舉例 含義
^ ^a 以a開頭(注意與[^]區分,後者表示匹配不在[^]中的元素)
$ a$ 以a結尾
\b \bsmart,smart\b 單詞邊界,即[A-Za-z0-9_]以外的字符
\B \Bsmart 非單詞邊界

舉個栗子說 \b 和 \B :函數

"You are smart, but she is smarter.".replace(/smart\b/,"kind");
//"You are kind, but she is smarter."

"You are smart, but she is smarter.".replace(/smart\B/,"kind");
//"You are smart, but she is kinder."

if(不懂){ 就置幾動手試試吧 (ง •̀_•́)ง }工具

5.數量詞

字符 含義
? 匹配前面的模式 0或1次 {0,1}
* 匹配前面的模式 0或屢次 {0,}
+ 匹配前面的模式 1或屢次 {1,}
{n} 匹配前面的模式 n次
{n,} 匹配前面的模式 至少n次
{n,m} 匹配前面的模式 至少n次,至多m次
{0,m} 匹配前面的模式 至多m次
x(?=y) 只有x後面緊跟着y時,才匹配x,可是y不是匹配結果的一部分。例如/smart(?=girl)/只有後面有girl時,才匹配smart,可是girl不是匹配結果的一部分。
x(?!y) 只有x後面不緊跟着y時,才匹配x。例如/\d+(?!\.)/只有一個數字後面沒有緊跟着小數點時纔會匹配該數字,/\d+(?!\.)/.exec("3.141")匹配結果是141

6.貪婪與懶惰(非貪婪)

默認是貪婪模式匹配,即匹配儘量多的字符。post

var regExp1 = /\d{3,6}/;
"1234567890".replace(regExp1, "X");
//"X7890"

若想手動開啓懶惰模式,須要在模式後加 ?

var regExp1 = /\d{3,6}?/;
"1234567890".replace(regExp1, "X");
//"X4567890"

7.分組與反向引用

分組又叫「子表達式」,把完整的正則表達式分紅一個個小組,而後反過來用「組號」去引用這些小組就叫「反向引用」。

用例子來講:

//無分組
var regExp1 = /abc{2}/; //這樣量詞{2}只能匹配到c一個字符

//分組
var regExp2 = /(abc){2}/; //這樣量詞{2}就能夠匹配到abc三個字符啦 
//同時 abc 也有了一個組號 $1

再看一個栗子:

var reg = /(\d{1}).*(\d{2}).*(\d{3})/;
"1sss23sss456".replace(reg,"$1?$2?$3");
//"1?23?456"

上面的栗子換一種使用分組的方式:

var reg = /(\d{1}).*(\d{2}).*(\d{3})/;
var result = reg.exec("1sss23sss456");
console.log(result[1]+"-"+result[2]+"-"+result[3]);
//"1-23-456"

組匹配很是有用,下面是一個匹配網頁標籤的例子:

var tagName = /<([^>]+)>[^<]*<\/\1>/; // \1 就是第一個組匹配的內容
tagName.exec("<b>bold</b>")[1]

上面代碼稍加修改,就能夠捕獲帶有屬性的標籤:

var html = '<b class="hello">Hello</b><i>world</i>';
var tag = /<(\w+)([^>]*)>(.*?)<\/\1>/g;

var match = tag.exec(html);

match[1] // "b"
match[2] // " class="hello""
match[3] // "Hello"

match = tag.exec(html);

match[1] // "i"
match[2] // ""
match[3] // "world"

非捕獲組: (?:x) 表示不返回該組匹配的內容,即匹配的結果中不出現這個括號。

經常使用方法

正則對象的方法

1.RegExp.prototype.test()

測試當前正則是否能匹配目標字符串,返回布爾值。

var reg = /\d{2}/;
var str = "1sss23sss456";
reg.test(str); //true

2.RegExp.prototype.exec()

在目標字符串中執行一次正則匹配操做,返回匹配的子字符串。

var reg = /\d{2}/;
var str = "1sss23sss456";
var result = reg.exec(str); 
result[0]; //23
result.index; //4
result.input; //"1sss23sss456"

3.RegExp.prototype.toString()

返回一個字符串,其值爲該正則對象的字面量形式。覆蓋了Object.prototype.toString() 方法。

var reg = /\d{2}/;
reg.toString(); // "/\d{2}/"

字符串對象的方法

1. str.replace()

返回替換後的值

var reg = /\d{2}/;
var str = "1sss23sss456";
str.replace(reg,"?"); //"1sss?sss456"

經常使用於消除首尾空格:

var str = '  abc def ggg   ';
str.replace(/^\s+|\s+$/g, '');
// 'abc def ggg'

replace方法的第二個參數能夠使用美圓符號來指代所替換的內容:

> $& 指代匹配的子字符串。
> $` 指代匹配結果前面的文本。
> $' 指代匹配結果後面的文本。
> $n 指代匹配成功的第n組內容,n是從1開始的天然數。
> $$ 指代美圓符號$。

replace方法的第二個參數還能夠是一個函數,將每個匹配內容替換爲函數的返回值。這個函數能夠接受多個參數,第一個參數是捕捉到的內容,第二個參數開始是捕捉到的組匹配(有多少個組匹配,就對應有多少個參數)。此外,最後還能夠添加兩個參數,倒數第二個是捕捉到的內容在整個字符串中的位置,最後一個參數是原字符串。下面是一個網頁模板替換的例子:

var prices = {
  'pr_1': '$1.99',
  'pr_2': '$7.99',
  'pr_3': '$9.99',
};

var template = '<span id="pr_1"></span><span id="pr_2"></span>';

template.replace(
  /(<span id=")(.*?)(">)(<\/span>)/, 
  function(match, p1, p2, p3 ,p4) {
    return p1 + p2 + p3 + prices[p2] + p4;
  });
//<span id="pr_1">$1.99</span><span id="pr_2"></span>

注意:第二個分組要加 ? 開啓懶惰模式,不然正則表達式默認的貪婪模式會匹配儘量多的字符。貪婪模式下,上面的例子中第二個分組會匹配到pr_1"></span><span id="pr_2 這一長串,從而沒法匹配到咱們但願的字符串。

2.match()

exec()相似,返回匹配的子字符串。

var reg = /\d{2}/;
var str = "1sss23sss456";
str.match(reg); //["23"]

exec()的區別在於:當正則表達式加了g標識符時,結果不一樣。看栗子:

var reg = /\d{2}/g;
var str = "1sss23sss456";
reg.exec(str); //["23"]
str.match(reg); //["23","45"]

3.search()

返回匹配的首字符的位置。

var reg = /\d{2}/;
var str = "1sss23sss456";
str.search(reg); //4

4.split()

返回分割後的數組。

var reg = /\d{2}/;
var str = "1sss23sss456";
str.split(reg); //["1sss","sss","6"]

小練習

  1. 寫一個匹配手機號的正則(第一位是1,第二位是[3,4,5,7,8]中的一個,後面還有9位數字)

  2. 寫一個匹配 2017-01-01 或 2017/01/01 這兩種格式日期的正則表達式

————答案:

  1. /^1[34578]\d{9}$/

  2. /^\d{4}[-/]\d{2}[-/]\d{2}$/

應用

1.使用正則改變數據結構

var re = /(\w+)\s(\w+)/;
var str = "John Smith";
var newstr = str.replace(re, "$2, $1");
console.log(newstr); //Smith, John

2.在多行中使用正則表達式

var s = "Please yes\nmake my day!";
s.match(/yes.*day/); // null
s.match(/yes[^]*day/); //'yes\nmake my day'

3.從URL中提取子域名

var url = "http://xxx.domain.com";
console.log(/[^.]+/.exec(url)[0]); //  "http://xxx"
console.log(/[^.]+/.exec(url)[0].substr(7)); //  "xxx"

匹配除了.以外的任意元素,一到多個字符。

「不會應用等於沒有學會」,熱烈歡迎小夥伴們在評論區補充平時用到正則表達式的地方,而後我會添加在文章裏,一塊兒收集吧 ヽ(•̀ω•́ )ゝ

參考:

1.正則表達式學習筆記

2.MDN RegExp文檔

3.實戰JS正則表達式

4.正則表達式30分鐘入門教程

相關文章
相關標籤/搜索