正則表示式歸納總結
正則表示式
1. 使用正則
建立正則表示式有兩種方式,一種是以字面量方式建立,另一種是使用RegExp
建構函式來建立。
var expression = / pattern / flags;
var expression = new RegExp( pattern / flags );
var expression = new RegExp( patternStr, flags );
// example
var regexp = /regexp/g;
var regexp = new RegExp('regexp', 'g');
var regexp = new RegExp(/regexp/g );
其中模式(pattern)部分可以是任何簡單或複雜的正則表示式,可以包含字元類、限定符、分組、向前查詢以及反向引用。
每個正則表示式都可帶有以或多個標誌(flags),用以表明正則表示式的行為。
注:flag
為可選項,表示匹配模式,主要有一下3種標誌。
- g : 表示全域性(global)模式,即模式將被應用於所有字串,而非在發現第一個匹配項時立即停止;
- i : 表示不區分大小寫(case-insensitive)模式,即在確定匹配項時忽略模式與字串的大小寫;
- m : 表示多行(multiline)模式,即在到達一行文字末尾時還會繼續查詢下一行中是否存在與模式匹配的項。
// global
var str = 'hello world, hello life',
reg1 = /hello/,
reg2 = /hello/g;
// 非全域性模式下,返回一個數組
// 第一個引數表示匹配的字串
// index表示的是匹配字串在文字中的起始位置
// input表示引用的文字
str.match(reg1); // [ 'hello', index: 0, input: 'hello world, hello life' ]
// 全域性模式下的匹配返回所有匹配的值
str.match(reg2); // [ 'hello', 'hello' ]
// case-insensitive
var cStr = 'Hello world',
cReg1 = /hello/,
cReg2 = /hello/i;
cReg1.exec(cStr); // null
cReg2.exec(cStr); // [ 'Hello', index: 0, input: 'Hello world' ]
// multiline
var mStr = 'hello world\n hello life',
mReg1 = /world$/,
mReg2 = /world$/m;
// 結果為null,因為沒有啟用多行,world並不算mStr的結尾
mStr.match(mReg1); // null
// 匹配成功,啟用多行之後,world變成第一行的結尾
mStr.match(mReg2); // [ 'world', index: 6, input: 'hello world\n hello life' ]
1.1 RegExp 例項屬性
每個RegExp例項物件都會存在下列屬性:
- global : 布林值,表示是否設定了g標誌
- ignoreCase : 布林值,表示是否設定了i標誌
- multiline : 布林值,表示是否設定了m標誌
- lastIndex : 整數,表示開始搜尋下一個匹配項的字元位置,從0算起
- source : 正則表示式字串表示,按照字面量形式而非傳入建構函式中的字串模式返回
var reg = /\[hello\] regexp/i;
reg.global; // false
reg.ignoreCase; // true
reg.multiline; // false
reg.lastIndex; // 0
reg.source; // \[hello\] regexp
var reg2 = new RegExp('\\[hello\\] regexp', 'ig');
reg2.global; // true
reg2.ignoreCase; // true
reg2.multiline; // false
reg2.lastIndex; // 0
reg2.source; // \[hello\] regexp 字面量形式返回
1.2 RegExp 例項方法
- pattern.exec(str)
exec
方法是RegExp的主要方法,主要用於提取捕獲組(這個後面後講到),它接收一個匹配字串作為引數,如果匹配成功,返回一個包含匹配項資訊的陣列;在沒有匹配到的時候返回null。
返回的陣列包含匹配的字串,同時另外包含兩個屬性:index 和 input。index表示的是匹配字串在文字中的起始位置,input表示匹配的字串。
在非全域性模式匹配下,如果字串中含有與模式匹配的多個子字串,那麼只會返回第一個匹配項的結果。返回的陣列中下標為0的位置表示匹配到的字串,其餘位置表示匹配到的捕獲組資訊;而在全域性模式下(g),如果依次執行exec
方法,依次返回的是每一個匹配項資訊的陣列。例如:
// 在非全域性模式下,始終返回第一個匹配項的資訊
var reg = /<(\/?)(\w+)([^>]*?)>/,
str = "<div class='hello'><b>hello</b><i>regexp</i></div>";
var matches = reg.exec(str);
matches[0]; // <div class='hello'>
matches[1]; // ""
matches[2]; // div
matches[3]; // class='hello'
matches.index; // 0
reg.lastIndex; // 0
var matches = reg.exec(str);
matches[0]; // <div class='hello'>
matches[1]; // ""
matches[2]; // div
matches[3]; // class='hello'
matches.index; // 0
reg.lastIndex; // 0
// 在全域性模式匹配下,找到第一個匹配項資訊之後,如果繼續執行,會在字串中繼續查詢下一個匹配項
var reg1 = /<(\/?)(\w+)([^>]*?)>/g,
str1 = "<div class='hello'><b>hello</b><i>regexp</i></div>";
var matches = reg1.exec(str1);
matches[0]; // <div class='hello'>
matches[1]; // ""
matches[2]; // div
matches[3]; // class='hello'
matches.index; // 0
reg1.lastIndex; // 19
var matches = reg1.exec(str1);
matches[0]; // <b>
matches[1]; // ""
matches[2]; // b
matches[3]; // ""
matches.index; // 19
reg1.lastIndex; // 22
- pattern.test(str)
test
方法主要用於檢測字串中是否存在與模式匹配的字串,常用語條件判斷。匹配成功返回true,否則返回false。例如:
var pattern = /\d{2}-\d{3}/,
str = '29-234',
str1 = '290-3345',
str2 = '1-33245';
pattern.test(str); // true
pattern.test(str1); // true
pattern.test(str2); // false
1.3 RegExp 建構函式屬性
建構函式靜態屬性,分別有一個長屬性名和一個短屬性名(Opera是例外,不支援短屬性名)。
長屬性名 | 短屬性名 | 說明 |
---|---|---|
input | $_ | 最近一次要匹配的字串 |
lastMatch | $& | 最近一次的匹配項 |
lastParen | $+ | 最近一次匹配的捕獲組 |
leftContext | $` | input字串中lastMatch之前的文字 |
multiline | $* | 布林值,表示是否所有表示式都使用多行模式 |
rightContext | $’ | input字串中lastMatch之後的文字 |
var pattern = /(.)or/,
str = 'this is a normal string or meaningful';
if (pattern.test(str)) {
console.log(RegExp.input); // this is a normal string or meaningful
console.log(RegExp.lastMatch); // nor
console.log(RegExp.lastParen); // n
console.log(RegExp.leftContext); // this is a
console.log(RegExp.multiline); // false
console.log(RegExp.rightContext); // mal string or meaningful
console.log(RegExp['$_']); // this is a normal string or meaningful
console.log(RegExp['$&']); // nor
console.log(RegExp['$+']); // n
console.log(RegExp['$`']); // this is a
console.log(RegExp['$*']); // false
console.log(RegExp['$\'']); // mal string or meaningful
}
1.4 用於模式匹配的String方法
- str.search(pattern)
它的引數是一個正則表示式,返回第一個與之匹配的子串的起始位置,如果找不到匹配的子串,它將返回-1。例如:
var str = 'JavaScript is not java',
pattern = /Java/i,
pattern2 = /Java/ig;
console.log(str.search(pattern)); // 0
console.log(str.search(pattern2)); // 0
注:如果search()的引數不是正則表示式,則首先會通過RegExp構造方法將它轉換成正則表示式,search()方法不支援全域性檢索,因為它忽略正則表示式引數中的修飾符g
- str.replace(subStr | pattern, replaceStr | function)
第一個引數是正則表示式或者是字串,第二個引數是要替換的字串。如果第一個引數是正則表示式,直接進行模式匹配,若為字串,則會檢索整個字串進行替換,而不會轉化為正則表示式。例如:
var str = 'JavaScript is not java',
pattern = /Java/i;
console.log(str.replace(pattern, 'live')); // liveScript is not java
console.log(str.replace('Java', 'live')); // liveScript is not java
// function
var str2 = '123-456-789',
pattern2 = /(\d+)/g;
str2.replace(pattern2, function(v) {
// 會執行三次
// 第一次列印123
// 第二次列印456
// 第三次列印789
console.log(v);
});
/**
* 第一個引數表示匹配的字串
* 第二個引數表示匹配的元組(如果沒有元組,則實際上回調函式只有三個值,即此時的d值會為undefined)
* 第三個引數表示字串匹配的開始索引
* 第四個引數表示匹配的字串
*/
str2.replace(pattern2, function(a, b, c, d) {
// 會執行三次
// 第一次列印123, 123, 0, 123-456-789
// 第二次列印456, 456, 4, 123-456-789
// 第三次列印789, 789, 8, 123-456-789
console.log(a, b, c, d);
});
// 此時沒有進行元組匹配
str2.replace(/\d+/g, function(a, b, c, d) {
// 會執行三次
// 第一次列印123, 0, 123-456-789, undefined
// 第二次列印456, 4, 123-456-789, undefined
// 第三次列印789, 8, 123-456-789, undefined
console.log(a, b, c, d);
});
- str.match(pattern)
match
方法接收一個正則表示式,如果是在全域性模式匹配下,匹配失敗返回null,匹配成功會返回一個數組,包含所有匹配的值;如果是非全域性模式,則返回第一個匹配項陣列資訊,陣列中第一個元素為匹配字串,餘下為匹配的捕獲組,另外這個陣列還有兩個屬性,index和input,index表示匹配字串的開始索引,input表示匹配的字串。例如:
var str3 = '[email protected]',
pattern3 = /^([a-zA-Z][\w\d]+)@([a-zA-Z0-9]+)(\.([a-zA-Z]+))+$/,
matches;
matches = str3.match(pattern3);
console.log(matches[0]); // [email protected]
console.log(matches[1]); // yuzhongzi_91
console.log(matches[2]); // sina
console.log(matches[3]); // .com
console.log(matches[4]); // com
console.log(matches.index); // 0
console.log(matches.input); // [email protected]
- str.split(pattern | subStr, [ howmany ])
split
可以接收兩個引數,第二個引數可選,表示返回陣列的最大長度。其中第一個引數是指定的分隔符,可以使正則表示式或者是字串。例如:
var str4 = 'Hope left life become a cat.',
pat1 = /\s/,
pat2 = ' ';
console.log(str4.split(pat1)); // [ 'Hope', 'left', 'life', 'become', 'a', 'cat.' ]
console.log(str4.split(pat2, 2)); // [ 'Hope', 'left' ]
2. 相關術語與操作符
2.1 精準匹配
如果一個字元不是特殊字元或操作符,則表示該字元必須在表示式中出現。例如,在
/test/
正則中,有4個術語,它們表示這些字元必須在一個字串中出現,才能匹配該模式。
簡單的理解:精準匹配可以理解為一對一匹配,即正則表示式中中的術語與字串中的字元對應。
2.2 匹配一類字元
表示匹配的一類代表一組特定含義的字元。例如:[abc]
就代表匹配”a”,”b”,”c”字元中的一個,而不是代表匹配一個特定的字元。具體有如下幾種:
字元 | 匹配內容 |
---|---|
[…] | 方括號內的任意字元 |
[^…] | 不在方括號內的任意字元 |
· | 除換行符和其他Unicode行終止符之外的任意字元 |
\w | 任意ASCII字元組成的單詞,等價於[a-zA-Z0-9_] |
\W | 任意不是ASCII字元組成的單詞,等價於[^a-zA-Z0-9_] |
\s | 任何Unicode空白符 |
\S | 任何非Unicode空白符的字元,注意w和S不同 |
\d | 任何ASCII數字,等價於[0-9] |
\D | 除了ASCII數字之外的任何字元,等價於[^0-9] |
\b | 單詞邊界 |
\B | 非單詞邊界 |
\t | 水平製表符 |
\v | 垂直製表符 |
\f | 換頁符 |
\r | 回車 |
\n | 換行符 |
\cA:\cZ | 控制符,例如:\cM匹配一個Control-M |
\u0000:\uFFFF | 十六進位制Unicode碼 |
\x00:\xFF | 十六進位制ASCII碼 |
// [abc] 表示匹配abc其中的一個
var str = 'abc',
pattern = /[abc]/;
console.log(str.match(pattern)); // [ 'a', index: 0, input: 'abc' ]
// [^abc] 表示不匹配abc字元中的任何一個
var str = 'abcd',
pattern = /[^abc]/;
console.log(str.match(pattern)); // [ 'd', index: 3, input: 'abcd' ]
// · 匹配除換行以外的字元
var str = '<p>I am a cat.</p>\n<b>what about you?</b>',
pattern = /.*/;
console.log(str.match(pattern)); // [ '<p>I am a cat.</p>', index: 0, input: '<p>I am a cat.</p>\n<b>what about you?</b>' ]
// \w 匹配包括下劃線的任意單詞字元
var str = 'Your are _ so cute #*& so | beatiful ',
pattern = /\w+/g;
console.log(str.match(pattern)); // [ 'Your', 'are', '_', 'so', 'cute', 'so', 'beatiful' ]
// \W 匹配任意非單詞字元
var str = 'Your are _ so cute #*& so | beatiful ',
pattern = /\W+/g;
console.log(str.match(pattern)); // [ ' ', ' ', ' ', ' ', ' #*& ', ' | ', ' ' ]
// \s 匹配空白字元
var str = 'Your \r\n\f ful',
pattern = /\s/g;
console.log(str.match(pattern)); // [ ' ', '\r', '\n', '\f', ' ' ]
// \S 匹配任意非空白字元
var str = 'Your \r\n\f ful',
pattern = /\S/g;
console.log(str.match(pattern)); // [ 'Y', 'o', 'u', 'r', 'f', 'u', 'l' ]
// \d 匹配任意數字
var str = '123helloworld34javascript',
pattern = /\d+/g;
console.log(str.match(pattern)); // [ '123', '34' ]
// \D 匹配任意非數字
var str = '123helloworld34javascript',
pattern = /\D+/g;
console.log(str.match(pattern)); // [ 'helloworld', 'javascript' ]
// \b 匹配單詞邊界
var str = 'I never come back',
pattern = /e\b/g;
if (pattern.test(str)) {
console.log(RegExp['$&']); // e
console.log(RegExp['$`']); // I never com
}
// \B 匹配非單詞邊界
var str = 'I never come back',
pattern = /e\B/g;
if (pattern.test(str)) {
console.log(RegExp['$&']); // e
console.log(RegExp['$`']); // I n
}
// \n 匹配換行符
var str = 'hello \n world',
pattern = /\n/;
console.log(str.match(pattern)); // [ '\n', index: 6, input: 'hello \n world' ]
// \u0000:\uFFFF 匹配十六進位制Unicode字元
var str = 'Visit W3School. Hello World!',
pattern = /\u0057/g;
console.log(str.match(pattern)); // [ 'W', 'W' ]
// \x00:\xFF 匹配十六進位制ASCII字元
var str = 'Visit W3School. Hello World!',
pattern = /\x57/g;
console.log(str.match(pattern)); // [ 'W', 'W' ]
2.3 轉義
與其他語言中的正則表示式類似,模式中使用的所有元字元都必須轉義。正則表示式中的元字元包括:
( [ { \ ^ $ | ? * + . } ] )
由於RegExp建構函式的模式引數是字串,所以在某些情況下需要雙重轉義。例如:
字面量模式 | 等價的字串 |
---|---|
/ |
“\\[abc\\]” |
/\w{2, 3}/ | “\\w{2, 3}” |
var reg1 = /\[abc\]/,
reg2 = new RegExp("\\[abc\\]"),
str = '[abc]';
console.log(str.match(reg1)); // [ '[abc]', index: 0, input: '[abc]' ]
console.log(str.match(reg2)); // [ '[abc]', index: 0, input: '[abc]' ]
console.log(reg1.source); // \[abc\]
console.log(reg2.source); // \[abc\]
2.4 匹配開始和結尾(^,$)
- 匹配一個字串的開始使用符號(^),例如: /^java/表示匹配已”java”開頭的字串
- 匹配一個字串的結尾使用符號(
),例如:/script /表示匹配已”script”結尾的字串 - 如果一個正則表示式中即出現了(^)又出現了(
),表示必須匹配整個候選字符串,例如:/javaScript /表示匹配整個”javaScript”字串
var str = 'javaScript is fun',
str2 = 'JavaScript',
reg1 = /^java/,
reg2 = /fun$/i,
reg3 = /^javascript$/i;
console.log(reg1.test(str)); // true
console.log(reg2.test(str)); // true
console.log(reg3.test(str)); // false
console.log(reg3.test(str2)); // true
2.5 重複
2.5.1 貪婪重複
要連續匹配四個’a’,我們可以使用/aaaa/
來進行匹配,但如果匹配的不止是四個,而是十幾個呢?想必是不方便的,在重複匹配的選項上,正則表示式提供了很多方式。
貪婪匹配 貪婪匹配表示儘可能多的匹配,例如/a+/
表示至少匹配一個”a”字元,即表示有多少個”a”就會匹配多少個,例如:
var str = 'aaaaa',
str1 = 'aaaaaaaaaa',
reg = /a+/;
console.log(reg.exec(str)); // [ 'aaaaa', index: 0, input: 'aaaaa' ]
console.log(reg.exec(str1)); // [ 'aaaaaaaaaa', index: 0, input: 'aaaaaaaaaa' ]
在貪婪重複上,正則表示式主要有以下方式:
字元 | 含義 |
---|---|
{x,y} | 匹配至少x次,最多y次 |
{x,} | 匹配至少x次 |
{x} | 匹配x次 |
? | 匹配0次或者1次, { 0, 1 } |
+ | 匹配至少1次, { 1, } |
* | 匹配0次或者多次, { 0, } |
// {2,3} 匹配至少2次,最多3次
var str = '.abc.def.xyz.com',
reg = /(.\w+){2,3}/;
console.log(str.match(reg)); // [ '.abc.def.xyz', '.xyz', index: 0, input: '.abc.def.xyz.com' ]
// {2,} 匹配至少2次
var str = '.abc.def.xyz.com',
reg = /(.\w+){2,}/;
console.log(str.match(reg)); // [ '.abc.def.xyz.com', '.com', index: 0, input: '.abc.def.xyz.com' ]
// {2} 匹配2次
var str = '.abc.def.xyz.com',
reg = /(.\w+){2}/;
console.log(str.match(reg)); // [ '.abc.def', '.def', index: 0, input: '.abc.def.xyz.com' ]
// ? 匹配0次或者1次
var str = '.abc//.def.xyz.com',
reg = /(.\w+\/?)?/;
console.log(str.match(reg)); // [ '.abc/', '.abc/', index: 0, input: '.abc//.def.xyz.com' ]
// * 匹配0次或者多次
var str = '.abc//.def.xyz.com',
reg = /(.\w+\/*)*/;
console.log(str.match(reg)); // [ '.abc//.def.xyz.com', '.com', index: 0, input: '.abc//.def.xyz.com' ]
// + 匹配1次或者多次
var str = '.abc//.def.xyz.com',
reg = /(.\w+\/+)+/;
console.log(str.match(reg)); // [ '.abc//', '.abc//', index: 0, input: '.abc//.def.xyz.com' ]
2.5.2 非貪婪重複
非貪婪模式就是在貪婪模式後面加上一個”?”,表示儘儘可能少的匹配,例如:
{x,y}?, {x,}?, {x}?, ??, +? *?
var str = 'aaaa',
str1 = '<p>Hello</p><p>Javascript</p>',
reg = /a+?/,
reg2 = /(<p>[^<]*<\/p>)+/,
reg3 = /(<p>[^<]*<\/p>)+?/;
console.log(reg.exec(str)); // [ 'a', index: 0, input: 'aaaa' ]
console.log(str1.match(reg2)); // [ '<p>Hello</p><p>Javascript</p>', '<p>Javascript</p>', index: 0, input: '<p>Hello</p><p>Javascript</p>' ]
console.log(str1.match(reg3)); // [ '<p>Hello</p>', '<p>Hello</p>', index: 0, input: '<p>Hello</p><p>Javascript</p>' ]
2.6 分組
使用()
表示分組,表示匹配一類字串,例如:/(\w\s)+/
表示匹配一個或者多個以字母和空格組合出現的字串
var str = 'a b c',
reg = /(\w\s)+/;
console.log(str.match(reg)); // [ 'a b ', 'b ', index: 0, input: 'a b c' ]
- 捕獲組
當用於模式匹配之後,匹配到的元組就被成為捕獲組。捕獲組對應著括號的數量,分別使用$1
,$2
…$99
…$x
表示匹配到的捕獲組,另外可以使用\1
,\2
…\99
…\x
表示引用捕獲組。
var str = '20170809',
str2 = '20170808',
reg = /(\d{4})(\d{2})(\d{2})/,
reg2 = /(\d{4})(\d{2})\2/;
console.log(str.replace(reg, '$1-$2-$3')); // 2017-08-09
console.log(str.replace(/a/, '$1/$2')); // 20170809
console.log(str.replace(reg2, '$1/$2')); // 20170809
console.log(str2.replace(reg2, '$1/$2')); // 2017/08
可以看到第三個列印與第四個列印之間的差異,原因是因為第三個沒有正則匹配項。
\x
表示引用,引用的是具體的匹配字串,也就是說上面例子中的\2
引用的是第二個捕獲組中的內容,其實應該對應的是”08”字串,因此”20170808”當然與”20170809”字串不匹配;反證可以看第四個匹配,驗證了上面的結果。
- 非捕獲組
若希望以()
分組的元組在匹配的時候不被捕獲,可以使用如下形式:
(?:str|pattern)
var str2 = '20170808',
reg2 = /(?:\d{4})(\d{2})\1/;
console.log(str2.replace(reg2, '$1')); // 08
2.7 或操作符(|)
用(|)表示或者的關係。例如:/a|b/
表示匹配字元”a”或者”b”,/(ab)+|(def)+/
表示匹配一次或者多次出現的”ab”或者”def”
2.8 斷言
正則表示式中的斷言大體分為兩類,先行斷言與後發斷言;在每一種斷言中又分為正環顧和負環顧,因此一共有四種斷言形式。
- 先行斷言
通俗的理解,先行斷言就是表示在匹配的字串後必須出現(正)或者不出現(負)什麼字串
(?=patten)
零寬正向先行斷言
(?!patten)
零寬負向先行斷言
// (?=patten)
var str = 'yuzhongzi91',
str2 = '123abc',
// 表示匹配以字母或者數字組成的,並且第一個字元必須為小寫字母開頭的字串
reg = /^(?=[a-z])([a-z0-9])+$/;
console.log(str.match(reg)); // [ 'yuzhongzi91', '1', index: 0, input: 'yuzhongzi91' ]
console.log(str2.match(reg)); // null
// (?!pattern)
var str = 'bb<div>I am a div</div><p>hello</p><i>world</i><p>javascript</p>',
// 表示匹配除了<p>標籤之外的標籤
// 分析:
// ?! 表示否定,這個可以先不用看
// \/?p\b 表示匹配"/p"或者"p"
// [^>]+ 表示匹配不是">"字元
// 如果沒有"?!"就表示匹配"<p>"標籤
// 而加上了"?!",就表示否定,因此就是匹配除了<p>標籤之外的標籤
reg = /<(?!\/?p\b)[^>]+>/g;
console.log(str.match(reg)); // [ '<div>', '</div>', '<i>', '</i>' ]
- 後發斷言(相容性,測試目前仍不支援)
通俗的理解,後發斷言就是表示在匹配的字串前必須出現(正)或者不出現(負)什麼字串
(?<=patten)
零寬正向後發斷言
(?<!patten)
零寬負向後發斷言
var str = '<p>hello</p>',
reg = /(?<=<p>).*(?=<\/p>)/;
console.log(str.match(reg)); // 相容情況下會匹配到"hello"字串
3. 正則表示式的編譯
正則表示式的兩個重要階段是編譯和執行。編譯發生在正則表示式第一次被建立的時候,而執行則是發生在我們使用編譯過的正則表示式進行字串匹配的時候。
因此,為了效能發麵的提升,建議對需要用到的正則表示式採用預定義(預編譯)的方式。
// 使用預定義方式
var str = '<a href="http://www.rynxiao.com">rynxiao.com</a>',
reg = /http:\/\/(?:.?\w+)+/,
start_time = new Date().getTime(),
i = 0,
end_time,
duration;
for (; i < 10000000; i++) {
reg.test(str);
}
end_time = new Date().getTime();
duration = end_time - start_time;
console.log(duration);
// 採用臨時建立新的正則表示式例項
var str = '<a href="http://www.rynxiao.com">rynxiao.com</a>',
start_time = new Date().getTime(),
i = 0,
end_time,
duration;
for (; i < 10000000; i++) {
/http:\/\/(?:.?\w+)+/.test(str);
}
end_time = new Date().getTime();
duration = end_time - start_time;
console.log(duration);
測試資料(可能不準,但大致上能說明一些問題)
執行次數 | 預編譯(ms) | 直接使用(ms) |
---|---|---|
100000 | 18 | 22 |
1000000 | 110 | 151 |
10000000 | 1355 | 1517 |
100000000 | 11395 | 12358 |
另外:用構造器(new RegExp(...))
建立正則表示式的使用。這種技術允許我們,在執行時通過動態建立字串構建和編譯一個正則表示式。對於構建大量重複的複雜表示式來說,這是非常有用的。
<div class="samurai ninja"></div>
<div class="ninja samurai"></div>
<div></div>
<span class="samurai ninja ronin"></span>
<script>
function findClassInElements(className, type) {
var elems = document.getElementsByTagName(type || "*");
var regex = new RegExp("(^|\\s)" + className + "(\\s|$)");
var results = [];
for (var i = 0; length = elems.length; i < length; i++) {
if (regex.test(elems[i].className)) {
results.push(elems[i]);
}
return results;
}
}
</script>
4. 常用正則表示式
4.1 去除首尾字串空格(trim)
var str = ' I am a cat. ',
reg = /^\s+|\s+$/;
console.log(str.replace(reg, '')); // I am a cat.
4.2 匹配電話號碼
var str = '0715-85624582-234',
str2 = '027-51486325',
// \d{3,4} 3-4位區號
// \d{8} 8位電話號碼
// (-(\d{3,4}))? 可能存在3-4位分機號
reg = /^(\d{3,4})-(\d{8})(?:-(\d{3,4}))?$/;
console.log(str.match(reg)); // [ '0715-85624582-234', '0715', '85624582', '234', index: 0, input: '0715-85624582-234' ]
console.log(str2.match(reg)); // [ '027-51486325', '027', '51486325', undefined, index: 0, input: '027-51486325' ]
4.3 匹配手機號碼
var str = '17985642351',
reg = /^1[3|4|5|7|8]\d{9}$/;
console.log(str.match(reg)); // [ '17985642351', index: 0, input: '17985642351' ]
4.4 匹配郵箱
var str3 = '[email protected]',
pattern3 = /^([\w-]+)(?:\.([\w-]+))*[email protected]([a-zA-Z0-9]+)(?:\.([a-zA-Z]+))+$/;
// [ '[email protected]', 'reg', 'xiao91', 'gmail', 'com', index: 0, input: '[email protected]' ]
console.log(str3.match(pattern3));
4.5 限制文字框只能輸入數字和小數點(二位小數點)
var reg = /^\d*\.?\d{0,2}$/;
console.log(reg.test('.4')); // true
console.log(reg.test('3')); // true
console.log(reg.test('3.3333')); // false
4.6 匹配中文
var str = '223我是abc一隻貓234',
reg = /[\u4E00-\u9FA5\uf900-\ufa2d]/g;
console.log(str.match(reg)); // [ '我', '是', '一', '只', '貓' ]
4.7 匹配標籤中的內容
var str = '<div>java<p>hello</p>script</div>',
// 或者為 /<div>(.*)<\/div>/ 但不能匹配'\n'
// /<div>((?:.|\s)*)<\/div>/
reg = /<div>[\s\S]*<\/div>/;
if (reg.test(str)) {
console.log(RegExp.$1); // java<p>hello</p>script
}
4.8 匹配帶有屬性的標籤
var str = '<div class="test" id="test" data-id="2345-766-sd24">hello</div>',
reg = /<([a-zA-Z]+)(\s*[a-zA-Z-]*?\s*=\s*".+?")*\s*>([\s\S]*?)<\/\1>/;
if (reg.test(str)) {
console.log(RegExp.$3); // hello
}
4.9 將數字轉化為中文大寫字元
var arrs = ["零","壹","貳","叄","肆","伍","陸","柒","捌","玖"],
reg = /\d/g,
str = '135268492580',
res;
res = str.replace(reg, function(v) {
return arrs[v];
});
console.log(res); // 壹叄伍貳陸捌肆玖貳伍捌零
4.10 查詢連結
var str = '<a href="http://www.rynxiao.com">rynxiao.com</a>',
reg = /http:\/\/(?:.?\w+)+/;
console.log(str.match(reg)[0]); // http://www.rynxiao.com
5. ES6新增
- 建構函式可以新增第二個規則引數
// es5新增第二個引數時會報錯
var regex = new RegExp(/test/, 'i');
// es6
var regex = new RegExp(/test/, 'ig');
regex.flags; // ig
- 添加了
u
修飾符,含義為”Unicode”模式,用來正確處理大於\uFFFF
的Unicode字元。
// \uD83D\uDC2A會被es5認為是兩個字元,加了u之後就會被認定為一個字元
/^\uD83D/u.test('\uD83D\uDC2A'); // false
/^\uD83D/.test('\uD83D\uDC2A'); // true
u
字元對正則表示式行為造成的影響,具體參考阮一峰的《ECMAScript 6入門》
- 添加了
y