深入淺出的javascript的正則表達式學習教程


深入淺出的javascript的正則表達式學習教程

閱讀目錄

了解正則表達式的方法

 RegExp對象表示正則表達式,它是對字符串執行模式匹配的工具;

 正則表達式的基本語法如下2種:

  1. 直接量語法:

         /pattern/attributes;

     2. 創建RegExp對象的語法

         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次,或指明一個非貪婪限定符,要匹配本身的話,使用\?

  \ 匹配本身的話,請使用\\

  { 標記限定符開始的地方,要匹配{ ,請使用\{

  | 指明多項中的一個選擇,可以理解含義為或的意思,匹配本身的話,使用\|

了解量詞

量詞

描述

n+

匹配任何至少包含一個n的字符串

n*

匹配零個或者多個n的字符串

n?

匹配零個或者1個n的字符串

n{x}

匹配包含x個n的序列字符串

n{x,y}

匹配至少x個,最多y個n的字符串

n{x,}

匹配至少x個的字符串

n$

匹配以n結尾的字符串

^n

匹配以n開頭的字符串

?=n

匹配其后緊接指定的n字符串

?!n

匹配其后沒有緊接指定的n字符串

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM