深刻淺出的javascript的正則表達式學習教程javascript
閱讀目錄php
瞭解正則表達式的方法html
RegExp對象表示正則表達式,它是對字符串執行模式匹配的工具;java
正則表達式的基本語法以下2種:正則表達式
/pattern/attributes;數組
2. 建立RegExp對象的語法ide
new RegExp(pattern,attributes);函數
參數:參數pattern是一個字符串,指定了正則表達式的模式;參數attributes是一個可選的參數,包含屬性 g,i,m,分別使用與全局匹配,不區分大小寫匹配,多行匹配;工具
@return 返回值:一個新的RegExp對象,具備指定的模式和標誌;學習
1-1. 支持正則表達式的String對象的方法
1. search()方法;該方法用於檢索字符串中指定的子字符串,或檢索與正 則表達式相匹配的字符串。
基本語法:stringObject.search(regexp);
@param 參數regexp能夠須要在stringObject中檢索的字符串,也能夠 是須要檢索的RegExp對象。
@return(返回值) stringObject中第一個與regexp對象相匹配的子串的起 始位置。若是沒有找到任何匹配的子串,則返回-1;
注意:search()方法不執行全局匹配,它將忽略標誌g,同時它也沒有regexp對象的lastIndex的屬性,且老是從字符串開始位置進行查找,老是返回的是stringObject匹配的第一個位置。
測試demo以下:
var str = "hello world,hello world"; // 返回匹配到的第一個位置(使用的regexp對象檢索) console.log(str.search(/hello/)); // 0 // 沒有全局的概念 老是返回匹配到的第一個位置 console.log(str.search(/hello/g)); //0 console.log(str.search(/world/)); // 6 // 也能夠是檢索字符串中的字符 console.log(str.search("wo")); // 6 // 若是沒有檢索到的話,則返回-1 console.log(str.search(/longen/)); // -1 // 咱們檢索的時候 能夠忽略大小寫來檢索 var str2 = "Hello"; console.log(str2.search(/hello/i)); // 0
2. match()方法;該方法用於在字符串內檢索指定的值,或找到一個或者多個正則表達式的匹配。該方法相似於indexOf()或者lastIndexOf(); 可是它返回的是指定的值,而不是字符串的位置;
基本語法:
stringObject.match(searchValue) 或者stringObject.match(regexp)
@param(參數)
searchValue 須要檢索字符串的值;
regexp: 須要匹配模式的RegExp對象;
@return(返回值) 存放匹配成功的數組; 它能夠全局匹配模式,全局匹配的話,它返回的是一個數組。若是沒有找到任何的一個匹配,那麼它將返回的是null;返回的數組內有三個元素,第一個元素的存放的是匹配的文本,還有二個對象屬性;index屬性代表的是匹配文本的起始字符在stringObject中的位置;input屬性聲明的是對stringObject對象的引用;
以下測試代碼:
var str = "hello world"; console.log(str.match("hello")); // ["hello", index: 0, input: "hello world"] console.log(str.match("Hello")); // null console.log(str.match(/hello/)); // ["hello", index: 0, input: "hello world"] // 全局匹配 var str2="1 plus 2 equal 3" console.log(str2.match(/\d+/g)); //["1", "2", "3"]
3. replace()方法:該方法用於在字符串中使用一些字符替換另外一些字符,或者替換一個與正則表達式匹配的子字符串;
基本語法:stringObject.replace(regexp/substr,replacement);
@param(參數)
regexp/substr; 字符串或者須要替換模式的RegExp對象。
replacement:一個字符串的值,被替換的文本或者生成替換文本的函數。
@return(返回值) 返回替換後的新字符串
注意:字符串的stringObject的replace()方法執行的是查找和替換操做,替換的模式有2種,既能夠是字符串,也能夠是正則匹配模式,若是是正則匹配模式的話,那麼它能夠加修飾符g,表明全局替換,不然的話,它只替換第一個匹配的字符串;
replacement 既能夠是字符串,也能夠是函數,若是它是字符串的話,那麼匹配的將與字符串替換,replacement中的$有具體的含義,以下:
$1,$2,$3....$99 含義是:與regexp中的第1到第99個子表達式相匹配的文本。
$& 的含義是:與RegExp相匹配的子字符串。
lastMatch或RegExp["$_"]的含義是:返回任何正則表達式搜索過程當中的最後匹配的字符。
lastParen或 RegExp["$+"]的含義是:返回任何正則表達式查找過程當中最後括號的子匹配。
leftContext或RegExp["$`"]的含義是:返回被查找的字符串從字符串開始的位置到最後匹配以前的位置之間的字符。
rightContext或RegExp["$'"]的含義是:返回被搜索的字符串中從最後一個匹配位置開始到字符串結尾之間的字符。
以下測試代碼:
var str = "hello world"; // 替換字符串 var s1 = str.replace("hello","a"); console.log(s1);// a world // 使用正則替換字符串 var s2 = str.replace(/hello/,"b"); console.log(s2); // b world // 使用正則全局替換 字符串 var s3 = str.replace(/l/g,''); console.log(s3); // heo word // $1,$2 表明的是第一個和第二個子表達式相匹配的文本 // 子表達式須要使用小括號括起來,表明的含義是分組 var name = "longen,yunxi"; var s4 = name.replace(/(\w+)\s*,\s*(\w+)/,"$2 $1"); console.log(s4); // "yunxi,longen" // $& 是與RegExp相匹配的子字符串 var name = "hello I am a chinese people"; var regexp = /am/g; if(regexp.test(name)) { //返回正則表達式匹配項的字符串 console.log(RegExp['$&']); // am //返回被搜索的字符串中從最後一個匹配位置開始到字符串結尾之間的字符。 console.log(RegExp["$'"]); // a chinese people //返回被查找的字符串從字符串開始的位置到最後匹配以前的位置之間的字符。 console.log(RegExp['$`']); // hello I // 返回任何正則表達式查找過程當中最後括號的子匹配。 console.log(RegExp['$+']); // 空字符串 //返回任何正則表達式搜索過程當中的最後匹配的字符。 console.log(RegExp['$_']); // hello I am a chinese people } // replace 第二個參數也能夠是一個function 函數 var name2 = "123sdasadsr44565dffghg987gff33234"; name2.replace(/\d+/g,function(v){ console.log(v); /* * 第一次打印123 * 第二次打印44565 * 第三次打印987 * 第四次打印 33234 */ }); /* * 以下函數,回調函數參數一共有四個 * 第一個參數的含義是 匹配的字符串 * 第二個參數的含義是 正則表達式分組內容,沒有分組的話,就沒有該參數, * 若是沒有該參數的話那麼第四個參數就是undefined * 第三個參數的含義是 匹配項在字符串中的索引index * 第四個參數的含義是 原字符串 */ name2.replace(/(\d+)/g,function(a,b,c,d){ console.log(a); console.log(b); console.log(c); console.log(d); /* * 如上會執行四次,值分別以下(正則使用小括號,表明分組): * 第一次: 123,123,0,123sdasadsr44565dffghg987gff33234 * 第二次: 44565,44565,11,123sdasadsr44565dffghg987gff33234 * 第三次: 987,987,22,123sdasadsr44565dffghg987gff33234 * 第四次: 33234,33234,28,123sdasadsr44565dffghg987gff33234 */ });
4. split()方法: 該方法把一個字符串分割成字符串數組。
基本語法如:stringObject.split(separator,howmany);
@param(參數)
1. separator[必填項],字符串或正則表達式,該參數指定的地方分割stringObject;
2. howmany[可選] 該參數指定返回的數組的最大長度,若是設置了該參數,返回的子字符串不會多於這個參數指定的數組。若是沒有設置該參數的話,整個字符串都會被分割,不考慮他的長度。
@return(返回值) 一個字符串數組。該數組經過在separator指定的邊界處將字符串stringObject分割成子字符串。
測試代碼以下:
var str = "what are you doing?"; // 以" "分割字符串 console.log(str.split(" ")); // 打印 ["what", "are", "you", "doing?"] // 以 "" 分割字符串 console.log(str.split("")); /* * 打印:["w", "h", "a", "t", " ", "a", "r", "e", " ", "y", "o", "u", " ", "d", "o", "i", "n", * "g", "?"] */ // 指定返回數組的最大長度爲3 console.log(str.split("",3)); // 打印 ["w", "h", "a"]
1-2 RegExp對象方法
1. test()方法:該方法用於檢測一個字符串是否匹配某個模式;
基本語法:RegExpObject.test(str);
@param(參數) str是須要檢測的字符串;
@return (返回值) 若是字符串str中含有與RegExpObject匹配的文本的話,返回true,不然返回false;
以下測試代碼:
var str = "longen and yunxi"; console.log(/longen/.test(str)); // true console.log(/longlong/.test(str)); //false // 或者建立RegExp對象模式 var regexp = new RegExp("longen"); console.log(regexp.test(str)); // true
2. exec()方法: 該方法用於檢索字符串中的正則表達式的匹配。
基本語法:RegExpObject.exec(string)
@param(參數):string【必填項】要檢索的字符串。
@return(返回值):返回一個數組,存放匹配的結果,若是未找到匹配,則返回值爲null;
注意:該返回的數組的第一個元素是與正則表達式相匹配的文本,該方法還返回2個屬性,index屬性聲明的是匹配文本的第一個字符的位置;input屬性則存放的是被檢索的字符串string;該方法若是不是全局的話,返回的數組與match()方法返回的數組是相同的。
以下測試代碼:
var str = "longen and yunxi"; console.log(/longen/.exec(str)); // 打印 ["longen", index: 0, input: "longen and yunxi"] // 假如沒有找到的話,則返回null console.log(/wo/.exec(str)); // null
瞭解正則中的普通字符
字母,數字,漢字,下劃線及一些沒有特殊定義的標點符號,都屬於普通字符,正則中的普通字符,在匹配字符串的時候,匹配與之相同的字符便可~ 好比以下代碼:
var str = "abcde";
console.log(str.match(/a/)); // ["a", index: 0, input: "abcde"]
如上代碼,字符串abcde匹配a的時候,匹配成功,索引位置從0開始;
瞭解正則中的方括號[]的含義
方括號包含一系列字符,可以匹配其中任意一個字符, 如[abc]能夠匹配abc中任意一個字符,使用[^abc]包含的字符abc,則可以匹配abc字符以外的任何一個字符,只能是一個字符。以下的含義:
[abc]: 查找在方括號中的任意一個字符;
[^abc]: 查找不在方括號中的任意一個字符;
[0-9]: 查找0-9中的任意一個數字;
[a-z]: 查找從小寫a到z中的任意一個字符;
(red|blue|green); 查找小括號中的任意一項,小括號中的 | 是或者的意思;
列舉1:表達式[bcd][bcd] 匹配 "abcde"時候,匹配成功,內容是bc,匹配到的位置開始於1,結束與3;以下代碼:
var str = "abcde";
console.log(str.match(/[bcd][bcd]/)); // ["bc", index: 1, input: "abcde"]
理解javascript中的元字符
元字符 | 描述 |
. |
查找任意的單個字符,除換行符外 |
\w |
任意一個字母或數字或下劃線,A_Za_Z0_9,_中任意一個 |
\W |
查找非單詞的字符,等價於[^A_Za_z0_9_] |
\d |
匹配一個數字字符,等價於[0-9] |
\D |
匹配一個非數字字符,等價於[^0-9] |
\s |
匹配任何空白字符,包括空格,製表符,換行符等等。等價於[\f\n\r\t\v] |
\S |
匹配任何非空白字符,等價於[^\f\n\r\t\v] |
\b |
匹配一個單詞邊界,也就是指單詞和空格間的位置,好比’er\b’能夠匹配」never」中的」er」,可是不能匹配」verb」中的」er」 |
\B |
匹配非單詞邊界,’er\B’能匹配’verb’中的’er’,但不能匹配’never’中的’er’ |
\0 |
查找NUL字符。 |
\n |
匹配一個換行符 |
\f |
匹配一個換頁符 |
\r |
匹配一個回車符 |
\t |
匹配一個製表符 |
\v |
匹配一個垂直製表符 |
\xxx |
查找一個以八進制數xxx規定的字符 |
\xdd |
查找以16進制數dd規定的字符 |
\uxxxx |
查找以16進制數的xxxx規定的Unicode字符。 |
1. 元字符. 用於匹配任何單個字符(除了換行符之外);
基本語法:new RegExp(「regexp.」) 或者直接量語法 /regexp./
好比代碼以下:
var str = "abcde";
console.log(str.match(/a.c/)); // ["abc", index: 0, input: "abcde"]
2. \w; 查找任意一個字母或數字或下劃線,等價於A_Za_z0_9,_
基本語法:new RegExp(「\w」); 或 直接量語法:/\w/
好比代碼以下:
var str = "abcde";
// 匹配單個字符,找到一個直接返回
console.log(str.match(/\w/)); // ["a", index: 0, input: "abcde"]
// 匹配全部字符
console.log(str.match(/\w+/)); //["abcde", index: 0, input: "abcde"]
3. \W; 查找非單詞的字符,等價於[^A_Za_z0_9_]
基本語法:new RegExp(「\W」) 或直接量 /\W/
var str = "abcde";
// 匹配單個字符,沒有找到返回null
console.log(str.match(/\W/)); // null
4. \d;匹配與一個數字字符,等價於[0-9];
基本語法:new RegExp(「\d」); 或 直接量語法:/\d/
代碼以下:
var str = "abcde111";
console.log(/\d/g.exec(str)); // ["1", index: 5, input: "abcde111"]
5. \D; 匹配一個非數字字符,等價於[^0-9]
基本語法:new RegExp(「\D」) 或直接量 /\D/
以下測試代碼:
var str = "abcde111";
console.log(/\D+/g.exec(str)); // ["abcde", index: 0, input: "abcde111"]
6. \s;匹配任何空白字符,包括空格,製表符,換行符等等。等價於[\f\n\r\t\v]
基本語法:new RegExp(「\s」) 或直接量 /\s/
以下測試代碼:
var str="Is this all there is?";
console.log(/\s/g.exec(str)); // [" ", index: 2, input: "Is this all there is?"]
7. \S;匹配任何非空白字符,等價於[^\f\n\r\t\v]
基本語法:new RegExp(「\S」) 或直接量 /\S/
以下測試代碼:
var str="Is this all there is?";
console.log(/\S+/g.exec(str)); // ["Is", index: 0, input: "Is this all there is?"]
8. \b; 匹配一個單詞邊界,也就是指單詞和空格間的位置,好比’er\b’能夠匹配」never」中的」er」,可是不能匹配」verb」中的」er」
基本語法:new RegExp(「\bregexp」) 或直接量 /\bregexp/
以下測試代碼:
var str="Is this all there is?";
console.log(/\bthis\b/g.exec(str)); // ["this", index: 3, input: "Is this all there is?"]
9. \B; 匹配非單詞邊界,’er\B’能匹配’verb’中的’er’,但不能匹配’never’中的’er’
基本語法:new RegExp(「\Bregexp」) 或直接量 /\Bregexp/
測試代碼以下:
var str="Is this all there is?";
console.log(/\Bhi/g.exec(str)); // ["hi", index: 4, input: "Is this all there is?"]
10. \n; 匹配一個換行符;返回換行符被找到的位置。若是未找到匹配,則返回 -1。
基本語法:new RegExp(「\n」) 或直接量 /\n/
以下測試代碼:
var str="Is this all \nthere is?";
console.log(/\n/g.exec(str)); // ["換行符", index: 12, input: "Is this all ↵there is?"]
11. \xxx; 查找一個以八進制數xxx規定的字符,若是未找到匹配,則返回 null。
基本語法:new RegExp(「\xxx」) 或直接量 /\xxx/
以下測試代碼:
var str="Visit W3School. Hello World!";
console.log(/\127/g.exec(str)); // ["W", index: 6, input: "Visit W3School. Hello World!"]
如上代碼分析:127的八進制轉換爲10進制的值等於 1*8的二次方 + 2*8的一次方 + 7*8的0次方 = 64 + 16 + 7 = 87 而W的ASCLL編碼轉換爲10進制也是87,所以打印W
12. \xdd;查找以16進制數dd規定的字符。若是未找到匹配,則返回 null。
基本語法:new RegExp(「\xdd」) 或直接量 /\xdd/
以下測試代碼:
var str="Visit W3School. Hello World!";
console.log(/\x57/g.exec(str)); // ["W", index: 6, input: "Visit W3School. Hello World!"]
W的16進制數等於57;
13.\uxxxx; 查找以16進制數的xxxx規定的Unicode字符。
基本語法:new RegExp(「\uxxx」) 或直接量 /\uxxx/
以下測試代碼:
var str="Visit W3School. Hello World!";
console.log(/\u0057/g.exec(str)); // ["W", index: 6, input: "Visit W3School. Hello World!"]
RegExp特殊字符中的須要轉義字符
須要轉義的特殊字符前面加 \
$ 匹配輸入字符串的結尾位置,若是須要匹配$自己的話,使用\$
^ 匹配輸入字符串的開始位置,匹配^自己的話,使用\^
* 匹配前面的子表達式的零次或者屢次,匹配*自己的話,使用\*
+ 匹配子表達式的1次或者屢次,匹配+自己的話,使用\+
. 匹配除換行符以外的任何一個字符,匹配.自己的話,使用\.
[ 匹配一箇中括號開始,匹配自己的,使用\[
? 匹配前面的子表達式的零次或者1次,或指明一個非貪婪限定符,要匹配自己的話,使用\?
\ 匹配自己的話,請使用\\
{ 標記限定符開始的地方,要匹配{ ,請使用\{
| 指明多項中的一個選擇,能夠理解含義爲或的意思,匹配自己的話,使用\|
瞭解量詞
1. n+ 匹配至少包含一個或者多個n的字符串。
基本語法:new RegExp(「n+」) 或直接量 /n+/
以下測試代碼:
var str = "hello longen"; // 匹配至少一個或者多個l的字符串 console.log(str.match(/l+/g)); //["ll", "l"] // 匹配至少一個或者多個字母數字或者下劃線 console.log(str.match(/\w+/g)); //["hello", "longen"]
2. n* 匹配零個或者多個n的字符串。
基本語法:new RegExp(「n*」) 或直接量 /n*/
以下測試代碼:
var str = "hello longen hello"; // 匹配至少零個或者多個l的字符串 // 能夠匹配多個l或者不匹配l 全局匹配 console.log(str.match(/el*/g)); //["ell", "e", "ell"] // 能夠匹配多個u或者不匹配u 全局匹配 console.log(str.match(/hu*/g)); //["h", "h"]
3. n?匹配零個或者1個n的字符串,能夠匹配n字符串,也能夠只匹配一個n;先儘可能匹配,如沒有匹配到,就回溯,再進行不匹配;
基本語法:new RegExp(「n?」) 或直接量 /n?/
以下測試代碼:
var str = "hello longen hello"; // 匹配至少零個或者1個l的字符串 console.log(str.match(/el?/g)); //["el", "e", "el"] // 能夠匹配1個u或者不匹配u 全局匹配 console.log(str.match(/hu?/g)); //["h", "h"]
4. n{x} 匹配包含x個的n的序列字符串。X必須是數字。
基本語法:new RegExp(「n{x}」) 或直接量 /n{x}/
以下測試代碼:
var str="100, 1000 or 10000?"; // 匹配4個數字的 匹配到1000和10000 console.log(str.match(/\d{4}/g)); //["1000", "1000"]
5. n{x,y} 匹配包含至少x個的n字符串,最多y個n字符串。
基本語法:new RegExp(「n{x,y}」) 或直接量 /n{x,y}/
以下測試代碼:
var str="100, 1000 or 10000?"; // 匹配最小3個數字,最多四個數字的 匹配到100,1000和10000 console.log(str.match(/\d{3,4}/g)); //["100", "1000", "1000"]
6. n{x,} 匹配至少包含x個n序列的字符串;
基本語法:new RegExp(「n{x,}」) 或直接量 /n{x,}/
以下測試代碼:
var str="100, 1000 or 10000?"; // 匹配最小3個數字 匹配到100,1000和10000 console.log(str.match(/\d{3,}/g)); //["100", "1000", "1000"]
7. n$ 匹配任何以n結尾的字符串;
基本語法:new RegExp(「n$」) 或直接量 /n$/
以下測試代碼:
var str="my name is longen"; // 匹配以en結尾的字符串 console.log(str.match(/en$/g)); //["en"]
8. ^n 匹配任何以n開頭的字符串;
基本語法:new RegExp(「^n」) 或直接量 /^n/
以下測試代碼:
var str="my name is longen"; // 匹配以my開頭的字符串 console.log(str.match(/^my/g)); //["my"] // 匹配以na開頭的字符串,沒匹配到,返回null console.log(str.match(/^na/g)); //null
9. ?=n 匹配任何其後緊接指定字符串n的字符串;
基本語法:new RegExp(「regexp(?=n)」) 或直接量 /regexp(?=n)/
以下測試代碼:
var str="my name is longen"; // 匹配以na其後緊接m的字符串 // ?= 只是匹配位置,不會返回值 console.log(str.match(/na(?=m)/g)); //["na"]
10 ?!n 匹配任何其後不緊接n的字符串
基本語法:new RegExp(「regexp(?!n)」) 或直接量 /regexp(?!n)/
以下測試代碼:
var str="my name is longen"; // 匹配以na其後不緊接ma的字符串 // ?! 只是匹配位置,不會返回值 console.log(str.match(/na(?!ma)/g)); //["na"] console.log(str.match(/na(?!m)/g)); // null
11. ^ 以字符串開始的地方匹配,不匹配任何字符;
好比:表達式^aaa 在匹配字符串 「longen aaa bbb」的時候,匹配的結果是失敗的;由於^的含義是以某某字符串開始進行匹配;只有當aaa在字符串起始位置才能匹配成功;好比」aaa longen bbb」 才匹配成功;
12. $ 以字符串結束的地方匹配,不匹配任何字符;
好比:表達式aaa$ 在匹配字符串 「longen aaa bbb」的時候,匹配的結果是失敗的;由於$的含義是以某某字符串結束進行匹配;只有當aaa在字符串結束位置才能匹配成功;好比」longen bbb aaa」 才匹配成功;
13. \b 匹配一個單詞邊界,也就是單詞與空格之間的位置,不匹配任何字符;
以下測試代碼:
var str="my name is longen"; // 匹配單詞邊界的字符 console.log(str.match(/\bname\b/g)); //["name"] // 若是不是單詞邊界的地方,就匹配失敗 console.log(str.match(/\blong\b/g)); // null
14. | 左右兩邊表達式之間 「或」 關係,匹配左邊或者右邊。
以下測試代碼:
var str = "hello world"; // 使用|的含義是 或者 匹配成功 結果爲["hello "] //若是再次匹配的話 就是world console.log(str.match(/(hello | world)/g)); // ["hello "]
15:()的含義
在被修飾匹配次數的時候,括號中的表達式能夠做爲總體被修飾。取匹配結果的時候,括號中的表達式匹配到的內容能夠被單獨獲得。
貪婪模式與非貪婪模式講解
Javascript中的正則貪婪與非貪婪模式的區別是:被量詞修飾的子表達式的匹配行爲;貪婪模式在整個表達式匹配成功的狀況下儘量多的匹配;非貪婪模式在整個表達式匹配成功的前提下,儘量少的匹配;
一些常見的修飾貪婪模式的量詞以下:
{x,y} , {x,} , ? , * , 和 +
那麼非貪婪模式就是在如上貪婪模式後加上一個?(問號),就能夠變成非貪婪模式的量詞;以下:
{x,y}?,{x,}?,??,*?,和 +?
1. 什麼是貪婪模式?
先看以下代碼:
var str = "longen<p>我是中國人</p>yunxi<p>我是男人</p>boyboy"; // 貪婪模式 匹配全部字符 console.log(str.match(/<p>.*<\/p>/)[0]); // <p>我是中國人</p>yunxi<p>我是男人</p> // 後面加問號,變成非貪婪模式 console.log(str.match(/<p>.*?<\/p>/)[0]); // <p>我是中國人</p>
第一個console.log使用的是貪婪模式,咱們來理解下匹配的基本原理;
首先正則是 /<p>.*<\/p>/ 匹配;<p>匹配字符串第一個字符匹配失敗,接着往下,直接匹配到<p>時候,匹配成功,接着把匹配的控制權交給.*,從匹配到的<p>位置開始匹配,一直到</p>以前,接着把控制權交給</p>,接着在當前位置下往下匹配,所以匹配到</p>,匹配成功;因爲它是貪婪模式,在匹配成功的前提下,仍然會嘗試向右往下匹配,所以會匹配到兩個<p>標籤結束;可是非貪婪模式,也就是第二個console.log();他匹配到第一個p標籤成功後,它就不會再進行匹配,所以打印的值爲一個p標籤的內容了;
理解匹配成功前提下的含義: 上面咱們解釋了,貪婪模式是要等一個表達式匹配成功後,再往下匹配;好比咱們如今接着再看下們的表達式匹配代碼:
var str = "longen<p>我是中國人</p>yunxi<p>我是男人</p>boyboy"; // 貪婪模式 console.log(str.match(/<p>.*<\/p>yunxi/)[0]); //打印 <p>我是中國人</p>yunxi
如上代碼,打印出一個p標籤內容,咱們知道.*是貪婪模式匹配,若是按照上面的解釋會打印出2個p標籤的內容,由於這裏在匹配到p標籤後,會繼續匹配後面的yunxi字符串,直到整個表達式匹配成功,才提示匹配成功,所以當匹配到第一個yunxi後,第一個子表達式匹配成功,接着嘗試往右繼續匹配,<p></p>都匹配成功,可是yunxi不會匹配boyboy,因此第二次嘗試匹配的子表達式匹配失敗,所以只返回匹配成功後的第一個p標籤的內容了;
咱們如今再來看看非貪婪模式的含義:
以下代碼:
var str = "longen<p>我是中國人</p>yunxi<p>我是男人</p>boyboy<p>我是中國人2</p>yunxi<p>我是男人</p>boyboy"; // 非貪婪模式1 console.log(str.match(/<p>.*?<\/p>boyboy/)[0]); //<p>我是中國人</p>yunxi<p>我是男人</p>boyboy // 貪婪模式 console.log(str.match(/<p>.*<\/p>yunxi/)[0]); //<p>我是中國人</p>yunxi<p>我是男人</p>boyboy<p>我是中國人2</p>yunxi
咱們先看錶達式1,/<p>.*?<\/p>boyboy/ 匹配str字符串,首先先匹配到p標籤內容;可是因爲boyboy字符串一直沒有匹配到,所以會一直嘗試日後匹配,直到匹配到boyboy字符串後,才匹配成功,不然匹配失敗;因爲它是非貪婪模式,所以這時候它不會再往下進行匹配,因此匹配就結束了;所以第一個console輸出爲<p>我是中國人</p>yunxi<p>我是男人</p>boyboy;
咱們能夠再來看看貪婪模式 第二個console.log()輸出的; 正則表達式 /<p>.*<\/p>yunxi/ 匹配到第一個p標籤yunxi後,因爲它是貪婪的,它還想接着向右繼續匹配,直到匹配完成後,匹配成功,才結束,所以把全部p標籤後面跟隨yunxi的字符串都匹配到,且之間的全部的字符串都被返回;
理解正則表達式匹配原理
咱們先來理解下佔有字符和零寬度的含義。
1. 佔有字符和零寬度
在正則表達式匹配的過程當中,若是子表達式匹配到的是字符內容,而非位置的話,並被保存在匹配的結果當中,那麼就認爲該子表達式是佔有字符的;若是子表達式匹配的僅僅是位置,或者說匹配中的內容不保存到匹配的結果當中,那麼就認爲該子表達式是零寬度的。咱們先來理解下零寬度的列子,最多見的就是環視~ 它只匹配位置;好比順序環視;環視待會就講;
咱們先理解下匹配過程以下圖:
正則匹配方式 /abc/
匹配過程:首先由字符a取得控制權,從位置0開始進行匹配,a匹配a,匹配成功;接着往下匹配,把控制權交給b,那麼如今從位置1開始,往下匹配,匹配到字符串b,匹配成功,接着繼續往下匹配,位置是從2開始,把控制權交給c,繼續往下匹配,匹配到字符串c,匹配成功,因此整個表達式匹配成功;匹配結果爲 abc 匹配的開始位置爲0,結束位置爲3;
含有匹配優先量詞的匹配過程
以下:
源字符串abc,正則表達式爲ab?c ;量詞?能夠理解爲匹配優先量詞,在可匹配可不匹配的時候,會優先選擇匹配;當匹配不到的時候,再進行不匹配。先匹配b是否存在,若是不存在的話,就不匹配b;所以結果能夠匹配的有 abc,ac等
匹配過程:
首先由字符a取得控制權,從位置0開始匹配,a匹配到字符串a,匹配成功;接着繼續匹配,把控制權交給b,b如今就從位置1開始匹配;匹配到字符串b,匹配成功;接着就把控制權交給c,c從位置2開始繼續匹配,匹配字符串c,匹配成功;整個表達式匹配成功;假如b那會兒匹配不成功的話,它會忽略b,繼續匹配字符串c,也就是若是匹配成功的話,結果是ac;
所以abc匹配字符串abc,匹配的位置從0開始,到3結束。
若是匹配的結果爲ac的話,那麼匹配的位置從0開始,到2結束;
假如咱們把字符串改成abd,或者abe等其餘的,那麼當匹配到最後一個字符的時候,就匹配失敗;
含有忽略優先量詞的匹配過程
量詞?? 含義是 忽略優先量詞,在可匹配和可不匹配的時候,會選擇不匹配,這裏的量詞是修飾b字符的,因此b?? 是一個總體的。匹配過程以下
首先由字符a取得控制權,從位置0開始匹配,有」a」匹配a,匹配成功,控制權交給b?? ;首先先不匹配b,控制權交給c,由c來匹配b,匹配失敗,此時會進行回溯,由b??來進行匹配b,匹配成功,而後會再把控制權交給c,c匹配c,匹配成功,所以整個表達式都匹配成功;
理解正則表達式----環視
環視只進行子表達式匹配,不佔有字符,匹配到的內容不保存到最終的匹配的結果,是零寬度的,它匹配的結果就是一個位置;環視的做用至關於對所在的位置加了一個附加條件,只有知足了這個條件,環視子表達式才能匹配成功。環視有順序和逆序2種,順序和逆序又分爲確定和否認,所以共加起來有四種;可是javascript中只支持順序環視,所以咱們這邊來介紹順序環視的匹配過程;
以下說明:
1. (?=Expression):
順序確定環視,含義是所在的位置右側位置可以匹配到regexp.
2. (?!Expression)
順序否認環視,含義是所在的位置右側位置不能匹配到regexp
順序確定環視
先看以下圖:
首先咱們須要明白的是:^和$ 是匹配的開始和結束位置的;?= 是順序確定環視,它只匹配位置,不會佔有字符,所以它是零寬度的。這個正則的含義是:
以字母或者數字組成的,而且第一個字符必須爲小寫字母開頭;
匹配過程以下:
首先由元字符^取得控制權,須要以字母開頭,接着控制權就交給 順序確定環視 (?=[a-z]); 它的含義是:要求它所在的位置的右側是有a-z小寫字母開頭的才匹配成功,字符a12,第一個字符是a,所以匹配成功;咱們都知道環視都是匹配的是一個位置,不佔有字符的,是零寬度的,所以位置是0,把控制權交給[a-z0-9]+,它纔是真正匹配字符的,所以正則[a-z0-9]+從位置0開始匹配字符串a12,且必須以小寫字母開頭,第一個字母是a匹配成功,接着繼續從1位置匹配,是數字1,也知足,繼續,數字2也知足,所以整個表達式匹配成功;最後一個$符合的含義是以字母或者數字結尾的;
順序否認環視
當順序確定環視匹配成功的話,順序否認環視就匹配失敗,當順序確定環視匹配失敗的話,那麼順序否認環視就匹配成功;
咱們先看以下圖:
源字符串:aa<p>one</p>bb<div>two</div>cc
正則:<(?!/?p\b)[^>]+>
正則的含義是:匹配除<p>以外的其他標籤;
以下圖:
匹配過程以下:
首先由」<」 取得控制權,從位置0開始匹配,第一個位置和第二個位置都是字符a,所以匹配失敗~ 接着從位置2匹配,匹配到<, 匹配成功了,如今控制權就交給(?!/?p\b);?!是順序否認環視,只匹配一個位置,不匹配字符,這個先不用管,首先是 /? 取得控制權,它的含義是:可匹配/,或者不匹配/, 接着往下匹配的是p字符,匹配失敗,進行回溯,不匹配,那麼控制權就到一位了p字符,p匹配p,匹配成功,控制權就交給\b; \b的含義是匹配單詞的邊界符,\b就匹配到了 > ,結果就是匹配成功,子表達式匹配就完成了;/?p\b 就匹配成功了;因此(?!/?p\b) 這個就匹配失敗了;從而使表達式匹配失敗;咱們繼續往下匹配,從b字符開始,和上面同樣匹配失敗,當位置是從14開始的時候 < 字符匹配到」<」,匹配成功,把控制權又交給了(?!/?p\b), 仍是/?取得控制權,和上面匹配的邏輯同樣,最後?p\b匹配失敗了,可是(?!/?p\b) 就匹配成功了,所以這一次表達式匹配成功;以下代碼匹配:
var str = "aa<p>one</p>bb<div>two</div>cc";
// 匹配的結果爲div,位置從14開始 19結束
console.log(str.match(/<(?!\/?p\b)[^>]+>/)[0]);
理解正則表達式---捕獲組
捕獲組就是把正則表達式中子表達式匹配的內容,保存到內存中以數字編號或顯示命名的組裏,方便後面使用;能夠在正則表達式內部使用,也能夠在外部使用;
捕獲組有2種,一種是捕獲性分組,另外一種是 非捕獲性分組;
咱們先來看看捕獲性的分組語法以下:
捕獲組分組語法:(Expression)
咱們都知道中括號是表示範圍內選擇,大括號表示重複次數,小括號的含義是容許重複多個字符;
捕獲性分組的編號規則:編號是按照」(」出現的順序,從左到右,從1開始進行編號;
好比以下代碼:
// 分組的列子 console.log(/(longen){2}/.test("longen")); // false console.log(/(longen){2}/.test("longenlongen")); //true // 分組的運用 RegExp.$1 獲取小括號的分組 var str = 11122; /(\d+)/.test(str); console.log(RegExp.$1); // 11122 // 使用replace替換 使用分組 把內容替換 var num = "11 22"; var n = num.replace(/(\d+)\s*(\d+)/,"$2 $1"); console.log(n); // 22 11
反向引用
反向引用標識由正則表達式中的匹配組捕獲的子字符串。每一個反向引用都由一個編號或名稱來標識;並經過 」\編號」 表示法來進行引用;
// 反向引用 console.log(/(longen)\1/.test("longen")); // false console.log(/(longen)\1/.test("longenlongen")); // true
理解非捕獲性分組
並非全部分組都能建立反向引用,有一種分組叫作非捕獲性分組,它不能建立反向引用,要建立一個非捕獲性分組,只要在分組的左括號的後面緊跟一個問號與冒號就ok;非捕獲分組的含義咱們能夠理解爲以下:子表達式能夠做爲被總體修飾可是子表達式匹配的結果不會被存儲;以下:
// 非捕獲性分組 var num2 = "11 22"; /#(?:\d+)/.test(num2); console.log(RegExp.$1); //"" 咱們再來看下使用 非捕獲性分組來把頁面上的全部標籤都去掉,以下代碼: // 把頁面上全部的標籤都移除掉 var html = "<p><a href='http://baidu.com'>我來測試下</a>by <em>龍恩</em></p>"; var text = html.replace(/<(?:.|\s)*?>/g, ""); console.log(text); // 我來測試下by 龍恩
如上:咱們來分析下:正則/<(?:.|\s)*?>/g 的含義是:g是修飾符,全局匹配的含義;使用非捕獲性分組?: 的含義是 子表達式能夠做爲被總體修飾可是子表達式匹配的結果不會被存儲;所以:正則/<(?:.|\s)*?>/g 的含義變爲:匹配以< 開頭 及 > 結束的全部字符;(?:.|\s)*? 含義是:. 表明任意字符,| 含義是或者的意思,\s 是匹配空格的意思;*號修飾符的含義是零個或者多個的意思;後面的?(問號)表明可匹配,可不匹配的含義;優先是可匹配;總起來的意思是:全局匹配字符串html 中的 以<開頭 以>結尾的全部字符 替換成 空字符串,所以留下來就是文本;固然咱們使用捕獲性分組也能夠獲得一樣的結果~
反向引用詳細講解
捕獲性分組取到的內容,不只能夠在正則表達式外部經過程序進行引用,也能夠在正則表達式內部進行引用,這種引用方式就叫作反向引用。
反向引用的做用是:是用來查找或限定重複,查找或限定指定標識配對出現等。
捕獲性分組的反向引用的寫法如:\number
Number是十進制數字,即捕獲組的編號。
反向引用的匹配原理
捕獲分組在匹配成功時,會將子表達式匹配到的內容,保存到內存中一個以數字編號的組裏,能夠簡單的認爲是對一個局部變量進行了賦值,這時就能夠經過反向引用,引用這個局部變量的值。一個捕獲分組在匹配成功以前,它的內容能夠是不肯定的,一旦匹配成功了,它的內容就肯定了,反向引用的內容也就肯定了。
好比以下代碼:
var str = "longenaabcd"; console.log(str.match(/([ab])\1/)[0]);//aa
代碼分析:對於如上代碼中的正則 /([ab])\1/, 捕獲組中子表達式[ab];能夠匹配a,也能夠匹配b,可是若是匹配成功的話,那麼它的反向引用也就肯定了,若是捕獲分組匹配到的是a,那麼它的反向引用就只能匹配a,若是捕獲分組匹配到的是b,那麼它的反向引用就只能匹配到b;\1的含義是 捕獲分組匹配到是什麼,那麼它必須與捕獲分組到是相同的字符;也就是說 只能匹配到aa或者bb才能匹配成功;
該正則匹配的過程咱們能夠來分析下:
字符串匹配正則/([ab])\1/, 在位置0處開始匹配,0處字符是l,很明顯不知足,把控制權就交給下一個字符,一直到第6個字符,才匹配到a,匹配成功,把控制權交給\1, 也就是反向引用和分組中是相同的字符,所以也匹配a,字符串中下一個字符也是a,所以匹配成功,所以整個表達式找到匹配的字符,匹配的位置開始於6,結束與8;咱們再能夠匹配b,原理和上面同樣,這裏就再也不多解釋了;
正則表達式實戰
1. 匹配以數字結尾的;
正則:/\d+$/g;
2. 去掉空格;
var str = "我 是 龍 恩";
console.log(str.replace(/\s+/g,""));//我是龍恩
3. 判斷字符串是否是由數字組成;
var str = "123344我 是 龍 恩 1123344";
console.log(/^\d*$/.test(str)); //false
var str2 = "123445566";
console.log(/^\d*$/.test(str2)); // true
4. 電話號碼正則
分析以下:電話號碼有區號(3-4位數字),區號以後使用 」-」 與電話號碼鏈接;
區號正則:^\d{3,4}
電話號碼7~8位 正則 \d{7,8}
電話號碼也有分機號,分機號爲3-4位數字,非必填項,若是要填寫的話,則以」-」與電話號碼相鏈接。
正則(-\d{3,4})?
所以正則匹配電話號碼正則爲:
/^\d{3,4}-/d{7,8}(-\d{3,4})?$/;
5. 手機號碼正則
手機號碼須要匹配;手機號碼開頭不以0開始的,而且是11位數字,目前的手機號碼有以下開頭的:13,14,15,17,18開頭的;所以正則以下:
/(^1[3|4|5|7|8][0-9]{9}$)/
以下測試代碼:
var str = 15606512345;
var reg = /(^1[3|4|5|7|8][0-9]{9}$)/;
console.log(reg.test(str)); //true
6. 刪除字符串左右空格
// 刪除字符串兩側的空白 /* * 下面的正則的含義是以1個或者多個空白開頭的 * | 是或者的意思 或者以1個或者多個空白結尾的 * 也就是去掉頭部和尾部的1個或者多個空格 */ function trim(str) { return str.replace(/^\s+|\s+$/g,''); } var str1 = " 1234 "; console.log(trim(str1)); // 輸出去掉空格的 1234
7. 限制文本框只能輸入數字和小數點(二位小數點)
分析:開頭有0個或者多個數字,中間有0個或者1個小數點,小數點後面有0個或者最多2個數字;
正則:
/^\d*\.?\d{0,2}$/ //測試代碼以下: var reg = /^\d*\.?\d{0,2}$/; var str1 = .9; console.log(reg.test(str1)); // true var str2 = 1.99; console.log(reg.test(str2)); // true var str3 = "1a.99"; console.log(reg.test(str3)); // false
8.替換小數點前面的內容爲指定內容
var href = "aa.php?d=1"; var reg = href.replace(/\b^(\w*)(?=\.)/,"bb"); console.log(reg); // bb.php?d=1
代碼分析以下:
如上代碼的含義是 使用正則replace替換操做
找出以字母數字下劃線開頭的字符,前面以\b分隔單詞與邊界的地方
所以會找出第一個字符串中第一個開頭的字符,後面是以捕獲性分組來匹配
後面緊跟着一個.號的匹配,分組只匹配位置,不匹配字符,是零寬度的;
9. 匹配中文的正則
使用 Unicode,必須使用\u開頭,接着是字符編碼的四位16進製表現形式。
console.log(/[\u4E00-\u9FA5\uf900-\ufa2d]/g.test("我是")); //true
10. 返回字符串中 中文字符的個數。
分析:使用replace方法把不是中文字符所有替換成空
返回被替換的字符,所以是中文字符;
代碼以下:
var str = "111我是塗根華說得對aaaaa1234556"; var reg = /[^\u4E00-\u9FA5\uf900-\ufa2d]/g; var val = str.replace(reg,''); console.log(val); // 我是塗根華說得對 console.log(val.length); // 長度爲 8
11. 正則獲取ip地址的前三段
好比如:192.168.16.162 須要變成 192.168.16
分析:使用正則匹配 .號後面帶1-3位數字便可,
且以數字結尾的,把他們替換成空字符串。
代碼以下:
var ip = "192.168.16.162"; console.log(ip.replace(/\.\d{1,3}$/,""));// 192.168.16
12. 匹配標籤中的內容
好比匹配如代碼 <ul><li>aaa</li><li>bbb</li></ul>
分析: 想獲取ul中的內容,能夠對匹配的內容使用分組
而後打印RegExp.$1 就獲取到分組的內容了; 匹配全部字符
使用[\s\S]+ 空白和非空白的全部字符,且使用修飾符g表明全局的
以下代碼:
var str2 = "<ul><li>aaa</li><li>bbb</li></ul>"; str2.match(/<ul>([\s\S]+?)<\/ul>/g); console.log(RegExp.$1); //<li>aaa</li><li>bbb</li>
13. 匹配標籤中的文本。
匹配文本思路:能夠先把字符串內的全部標籤替換成空字符串
所以返回的就是文本了;
正則/<\/?[\s\S]+?>/gi
以下代碼:
var str3 = "<ul><li>aaa</li><li>bbb</li></ul>"; var c = str3.replace(/<\/?[\s\S]+?>/gi,""); console.log(c); // aaabbb
14. 正則獲取文件名
文件名有以下幾種:
1. c:\images\tupian\006.jpg
2. C:\006.JPG
3. "c:\\images\\tupian\\006.jpg";
4. "c:\\images\\tupian\\aa.jpg";
5. "c:/images/tupian/test2.jpg";
正則如:/[^\\\/]*[\\\/]+/gi;
上面的正則含義是:[^\\\/]* 不以一個\ 或者 2個\\ 或者 /(須要轉義,使用\)這樣的反斜槓開頭的
零個或者多個字符,後面緊跟以一個\ 或者 兩個\\ 或者 /(須要轉義,使用\)這樣一個或者多個分隔符
全局匹配;
代碼以下:
var s1 = "c:\\images\\tupian\\006.jpg", s2 = "c:\\images\\tupian\\aa.jpg", s3 = "c:/images/tupian/test2.jpg"; function getFileName(str){ var reg = /[^\\\/]*[\\\/]+/gi; str = str.replace(reg,''); return str; } console.log(getFileName(s1)); // 006.jpg console.log(getFileName(s3)); // test2.jpg
15. 絕對路徑變成相對路徑
好比絕對路徑 http://172.16.28.162/images/a.jpg 須要替換成
./images/a.jpg
使用正則匹配 http:// //須要使用轉義字符轉義的 繼續匹配除/之外的任何一個字符
直到有反斜槓/爲止;而後替換成 . 字符
代碼以下:
var reg = /http:\/\/[^\/]+/g; var r1 = "http://172.16.28.162/images/a.jpg"; console.log(r1.replace(reg,'.')); // ./images/a.jpg
16. 用戶名正則
匹配規則:只能是中文,英文,數字,下劃線,4-16個字符;
匹配中文字符正則:/[\u4E00-\u9FA5\uf900-\ufa2d]/
\w是 匹配英文,數字,下劃線
測試代碼以下:
var reg = /^[\u4E00-\u9FA5\uf900-\ufa2d\w]{4,16}$/; var str = "我是12345678aa_123"; console.log(reg.test(str)); // true var str = "我是12345678aa_1235"; console.log(reg.test(str)); // 17位 false
17. 匹配英文地址
匹配規則:包含點,字母,空格,逗號,數字,可是開頭和結尾必須爲字母
分析:開頭必須爲字母能夠這樣寫 /^[a-zA-Z]/
結尾必須爲字母能夠這樣寫:/[a-zA-Z]+$/
中間包含點,字母,空格,逗號,數字的正則:/[\.a-zA-Z\s,0-9]*?/
外面的*號是0個或者多個,後面的問號? 表明無關緊要;有就匹配,沒有就不匹配;
測試代碼以下:
var reg = /^[a-zA-Z][\.a-zA-Z\s,0-9]*?[a-zA-Z]+$/; var str1 = "11aa"; console.log(reg.test(str1)); // false var str2 = "aa111aaa"; console.log(reg.test(str2)); // true
18 匹配價格
匹配規則: 開頭有0個或者多個數字,中間可能有一個小數點,後面有可能有0-2位小數
正則:/^\d*(\.\d{0,2})?$/
代碼以下測試
var reg = /^\d*(\.\d{0,2})?$/ var num1 = 12; console.log(reg.test(num1)); // true var num2 = .01; console.log(reg.test(num2)); // true var num3 = 1.01; console.log(reg.test(num3)); // true var num4 = "1.aa1"; console.log(reg.test(num4)); //false var num5 = "1.1a"; console.log(reg.test(num5)); //false
19. 身份證號碼的匹配
匹配規則:身份證號碼有15位或者18位,其中最後一位多是X,其餘全是數字
正則: /^(\d{14}|\d{17})(\d|[xX])$/
var reg = /^(\d{14}|\d{17})(\d|[xX])$/; var identity1 = "36232919578996x"; console.log(reg.test(identity1)); // true var identity2 = "36232919578996a"; console.log(reg.test(identity2)); // false // 16位 var identity3 = "362329195789961x"; console.log(reg.test(identity3)); // false
20. 單詞的首字母大寫
匹配字符串,讓其字符串的首個字母大寫
正則:/\b(\w)|\s(\w)/g
測試代碼以下:
function replaceReg(reg,str) { // 先轉換爲小寫 str = str.toLowerCase(); return str.replace(reg,function(m){ return m.toUpperCase(); }); } var reg = /\b(\w)|\s(\w)/g; var str = "aadfdfCC"; console.log(replaceReg(reg,str)); // Aadfdfcc
21. 驗證日期格式
日期格式有2種 第一種是yyyy-mm-dd 或 yyyy/mm/dd
分析 月和天數能夠有1位或者2位
正則:/^\d{4}[-\/]\d{1,2}[-\/]\d{1,2}$/;
測試代碼以下:
var reg = /^\d{4}[-\/]\d{1,2}[-\/]\d{1,2}$/; var d1 = "2015-12-1"; console.log(reg.test(d1)); //true var d2 = "2015-12-02"; console.log(reg.test(d2)); //true var d3 = "2015/12/12"; console.log(reg.test(d3)); // true
22. 驗證郵箱的正則表達式
思路分析: 郵箱的規則是: 由3部分組成
由1個或者多個字母數字下劃線和槓 + @ + 1個或者多個字母數字下劃線和槓 + . + 1個或者多個字母數字下劃線和槓
所以正則:/^([a-zA-Z_0-9-])+@([a-zA-Z_0-9-])+(\.[a-zA-Z_0-9-])+$/
測試代碼以下:
var reg = /^([a-zA-Z_0-9-])+@([a-zA-Z_0-9-])+(\.[a-zA-Z_0-9-])+/; var email1 = "tugenhua@126.com"; console.log(reg.test(email1)); //true var email2 = "879083421_aaAA@qqAAzz_AA.comaaa"; console.log(reg.test(email2)); // true
23. 匹配代碼中的a連接
好比<a href='http://www.baidu.com'>222</a> 匹配這樣的
使用正則:/<a[.\s]*href\s*=\s*'http:\/\/.*'>\w*<\/a>/gi;
測試代碼以下:
var reg = /<a[.\s]*href\s*=\s*'http:\/\/.*'>\w*<\/a>/gi; var html = "<div><a href='http://www.baidu.com'>222</a><p>344</p></div>"; console.log(html.match(reg)); // ["<a href='http://www.baidu.com'>222</a>"] var html2 = "<div><a href='http://www.baidu.com'>222</a><p>344</p><a href='http://www.baidu2.com'>333</a></div>"; console.log(html2.match(reg)); //["<a href='http://www.baidu.com'>222</a><p>344</p><a href='http://www.baidu2.com'>333</a>"]
24. 正則判斷標籤是否閉合
沒有閉合的標籤有2種 類型 一種像img標籤那樣的
<img src=""
還有一種像div或者p標籤那樣的
<div>aaa</div>
<p></p>
分析:先匹配起始標籤 如<img 或 <p 使用正則:/<[a-z]+/i
接着匹配標籤裏面的多個屬性 使用正則 /(\s*\w*?\s*=\s*.+?)*(\s*?>[\s\S]*?(<\/\1>)+|\s*\/>)/i
所以整個正則表達式合併爲 /<([a-z]+)(\s*\w*?\s*=\s*.+?)*(\s*?>[\s\S]*?(<\/\1>)+|\s*\/>)/i
正則分析以下:
首先咱們匹配像img標籤或者div標籤的開頭位置時候 <img 或 <div 使用正則 /<([a-z]+)/i 以 < 開始 [a-z]中任意一個字符,修飾符+是一個或者多個字符 i表明不區分大小寫
(\s*\w*?\s*=\s*.+?)*的含義是:好比<img src = "" 或 <div id = "" 先\s*匹配0個或多個空白 \w* 匹配0個或者多個(數字或者字母或下劃線) 後面的問號?(儘量少的匹配)
接着\s* 匹配0個或者多個空白 = 號緊接後面的 \s* 也是匹配0個或者多個空白 .+? 的含義是匹配除換行符以外的任意一個或多個字符(儘量少的匹配);
下面咱們繼續看標籤的閉合 標籤閉合有2種,一種像img這樣的 <img src=""/> 還有一種是 <div></div>這樣的;
若是是相似img標籤這樣的話,匹配結束字符爲 /> 匹配正則爲:(\s*\/>); 若是是div這樣的話 正則爲:(\s*?>[\s\S]*?<\/\1>)
<\/\1> 的含義是:指的是 ([a-z]+) 這個分組
整個正則 /<([a-z]+)(\s*\w*?\s*=\s*".+?")*(\s*?>[\s\S]*?<\/\1>)|\s*\/>/i
注意:在元字符* 或者 + 號後加一個問號(?) 目的是 儘量少的匹配;
var reg = /<([a-z]+)(\s*\w*?\s*=\s*".+?")*(\s*?>[\s\S]*?<\/\1>)|\s*\/>/i; var str1 = "<img src='aa' />"; var str2 = "<div></div>"; console.log(reg.test(str1)); // true console.log(reg.test(str2)); // true var str3 = "<img src='bb'"; console.log(reg.test(str3)); // false var str4 = "<div>aaa"; console.log(reg.test(str4)); // false //可是如上正則對下面的這個demo列子就不適用了;相同的標籤嵌套沒有閉合的狀況下 以下 var str5 = "<div><div>aaa</div>"; console.log(reg.test(str5)); // true 其實是false 由於有沒有閉合標籤
25. 獲取標籤裏面的內容
正則和上面同樣 只是使用了一個分組後,再獲取那個分組便可;
var str = "<div>111</div>"; str.match(/<([a-z]+)(\s*\w*?\s*=\s*".+?")*\s*?>([\s\S]*?)<\/\1>/); console.log(RegExp.$3); // 111
26. 正則判斷是否爲數字和字母的混合
規則:字母和數字的混合
正則如: /^(([a-z]+)([0-9]+)|([0-9]+([a-z]+)))[a-z0-9]*$/i
分析:^([a-z]+)([0-9]+) 含義是 以1個或多個字母開頭 後面緊跟1個或者多個數字
^([0-9]+([a-z]+)) 或者是以1個或者多個數字開頭 後面緊跟1個或者多個字母
[a-z0-9]*$ 後面還能夠緊跟數字或者字母0個或者多個
測試代碼以下:
var reg = /^(([a-z]+)([0-9]+)|([0-9]+([a-z]+)))[a-z0-9]*$/i; var str1 = "aaaa"; var str2 = "aa22"; var str3 = "111sddtr"; var str4 = "問問啊啊啊ass"; var str5 = "1111ssdsd111sasddas"; console.log(reg.test(str1)); //false console.log(reg.test(str2)); // true console.log(reg.test(str3)); // true console.log(reg.test(str4)); // false console.log(reg.test(str5)); // true
27. 將阿拉伯數字轉換爲中文大寫字符
var arrs = ["零","壹","貳","叄","肆","伍","陸","柒","捌","玖"]; function replaceReg2(reg,str){ return str.replace(reg,function(m){return arrs[m];}) } var reg = /\d/g; var str1 = '13889294444'; var str2 = '12889293333'; var str3 = '23445567'; console.log(replaceReg2(reg,str1)); // 壹叄捌捌玖貳玖肆肆肆肆 console.log(replaceReg2(reg,str2)); // 壹貳捌捌玖貳玖叄叄叄叄 console.log(replaceReg2(reg,str3)); // 貳叄肆肆伍伍陸柒
28. 替換文本中的url爲連接
好比一段文本中有 aaaaahttp://www.baidu.combbbbb 須要替換成 aaaaa<a href="http://www.baidu.com">http://www.baidu.com</a>bbbbb
分析:最主要的仍是須要正則匹配http://www.baidu.com 的url
正則如:/http:\/\/\w*(\.\w*)+/ig;
測試代碼以下:
var str1 = "aaaaahttp://www.baidu.com bbbbb"; //var reg = /http:\/\/\w*(\.\w)+/ig; var reg = /http:\/\/\w*(\.\w*)+/ig; function replaceUrl(reg,str) { return str.replace(reg,function(r){ return "<a href='"+r+"'>"+r+"</a>"; }); } console.log(replaceUrl(reg,str1)); // aaaaa<a href='http://www.baidu.com'>http://www.baidu.com</a> bbbbb