JavaScript正則表達式(RegExp)

1.轉義字符

*轉義字符 *

  • \r叫做行結束符,

  • \n叫做換行符,

  • \t叫做製表符

var str = "abcde\"d\"f";
console.log(str);//abcde"d"f

多行字符串

第一種:

var test = "\
<div></div>\
<span><span>\
";

第二種方式:利用換行符\n

第三種:加號連接

 var test = "
<div></div>+
<span><span>+
";
2.正則表達式兩種創建方式

在這裏插入圖片描述
例如輸入郵箱是符合格式要求,如何輸入前兩位相同後兩位相同等

1.直接量(推薦)

var reg = /abc/;//我匹配的規則叫abc,字符串是否有abc連着的字符串
var reg = /abc/i;

(修飾符)
參數是一個可選的字符串,包含屬性 “g”、“i” 和 “m”,分別用於指定全局匹配、區分大小寫的匹配和多行匹配。
在這裏插入圖片描述
m (首先要匹配的字符串要是多行的,匹配開頭和結尾)

var reg = /^a/gm;
var str = "abcde\na";
console.log(str.match(reg));// ["a", "a"]

2.構造方法

var reg = new RegExp("abc");
var reg = new RegExp("abc","i");
var reg1 = new RegExp(reg);

這樣創建出來的reg和reg1雖然是一樣的。但是它們確實是兩個不同的對象。

var reg2 = RegExp(reg)

沒有了new的時候,它們兩個就是完全一樣的對象

3.正則表達式規則

在這裏插入圖片描述在這裏插入圖片描述

n+ :   {1,}   個數是一個到無窮個
n* :   {0,}   個數是0個到無窮個
n? :   {0,1}  個數是0個或一個

      var reg = /\w+/g/                    // \w ===  [0-9A-z]
      var str = "abc";
      console.log(str.match(reg));//["abc"]
      
      var reg = /\d+/g						//\d === [0-9]
      var str = "abc";
      console.log(str.match(reg));//null
      
      var reg = /\d*/g
      var str = "abc";
      console.log(str.match(reg));//["", "", "", ""]按照光標位置找0個到無窮個數字,因爲是貪婪匹配,所以就要儘可能的匹配的數量要多,每一個光標處都爲空,邏輯上爲空字符串也被匹配到了。
      
       var reg = /\d*/g
      var str = "abc4";
      console.log(str.match(reg));//["", "", "", "4", ""]因爲是貪婪匹配,用了*就是0個到多個那麼就不僅僅是隻匹配數字4就完了,它還要根據光標位置找邏輯上的空字符串
      
      var reg = /\w?/g;
      var str = "aaaaaaa";
      console.log(str.match(reg));// ["a", "a", "a", "a", "a", "a", "a", ""]按照光標位置找0個或者1個字母或者數字,最後一光標位置就是在最後一個a的後面在邏輯上的爲空


n{x}  {x}     個數就是x個
n{x,y} {x,y}  個數就是x到y個
n{x,} {x,}	  個數就是x到無窮個
      var reg = /\w{3}/g;
      var str = "aaaaaaa";
      console.log(str.match(reg));// ["aaa", "aaa"]
      
      var reg = /\w{3,5}/g;
      var str = "aaaaaaaaaaaaaa";
      console.log(str.match(reg));//  ["aaaaa", "aaaaa", "aaaa"]貪婪匹配先趕着長的來,5個的先來,然後就剩下4個也匹配到了
      
      var reg = /\w{1,}/g;
      var str = "aaaaaaaaaaaaaa";
      console.log(str.match(reg));//["aaaaaaaaaaaaaa"]
      

在這裏插入圖片描述

.  ===  [^\r\n]
\w ===  [0-9A-z]
\W ===  [^\w]
\d ===  [0-9]
\D ===  [^\d]
\s ===  [\t\n\r\f\v]
\S ===  [^\s]
\b ===  單詞邊界
\B ===  非單詞邊界
4.正則表達式方法
  • test()方法

正則表達式常用方法test(),它接受一個字符串參數。在模式與該參數匹配的情況下返回true,否則返回false。

用法:正則.test(字符串)

例1:判斷是否是數字

var str = '374829348791';
var re = /\D/;      //  \D代表非數字
if( re.test(str) ){   // 返回true,代表在字符串中找到了非數字。
    alert('不全是數字');
}else{
    alert('全是數字');
}
  • search()方法

在字符串搜索符合正則的內容,搜索到就返回出現的位置(從0開始,如果匹配的不只是一個字母,那隻會返回第一個字母的位置)
如果搜索失敗就返回 -1

用法:字符串.search(正則)

例子:在字符串中找字母b,且不區分大小寫

var str = 'abcdef';
var re = /B/i;
//var re = new RegExp('B','i'); 也可以這樣寫
alert( str.search(re) ); // 1
  • match方法

語法:

stringObject.match(searchvalue)
stringObject.match(regexp)
  1. searchvalue:必需。規定要檢索的字符串值。
  2. regexp:必需。規定要匹配的模式的 RegExp 對象。如果該參數不是 RegExp 對象,則需要首先把它傳遞給 RegExp 構造函數,將其轉換爲 RegExp 對象。
  3. 如果 regexp 沒有標誌 g,那麼 match() 方法就只能在 stringObject
    中執行一次匹配。如果沒有找到任何匹配的文本, match() 將返回 null。否則,它將返回一個數組。

例如:

"186a619b28".match(/\d+/g); // ["186","619","28"] 

如果上面的匹配不是全局匹配,那麼得到的結果如下:

`["186", index: 0, input: "186a619b28"]`
  • replace方法

replace 本身是JavaScript字符串對象的一個方法,它允許接收兩個參數:

replace([RegExp|String],[String|Function])

第1個參數可以是一個普通的字符串或是一個正則表達式.
第2個參數可以是一個普通的字符串或是一個回調函數.

如果第2個參數是回調函數,每匹配到一個結果就回調一次,每次回調都會傳遞以下參數:

  1. result: 本次匹配到的結果

  2. 1,…9: 正則表達式中有幾個(),就會傳遞幾個參數,1 9分別代表本次匹配中每個()提取的結果,最多9個

  3. offset:記錄本次匹配的開始位置

  4. source:接受匹配的原始字符串

以下是replace和JS正則搭配使用的幾個常見經典案例:
$1$2…表示第幾個子表達式

(1)實現字符串的trim函數,去除字符串兩邊的空格
複製代碼

String.prototype.trim = function(){
 
  //方式一:將匹配到的每一個結果都用""替換
  return this.replace(/(^\s+)|(\s+$)/g,function(){
    return "";
  });
 
  //方式二:和方式一的原理相同
  return this.replace(/(^\s+)|(\s+$)/g,'');
};

^s+ 表示以空格開頭的連續空白字符,s+$ 表示以空格結尾的連續空白字符,加上() 就是將匹配到的結果提取出來,由於是 | 的關係,因此這個表達式最多會match到兩個結果集,然後執行兩次替換:

String.prototype.trim = function(){
  /**
   * @param rs:匹配結果
   * @param $1:第1個()提取結果
   * @param $2:第2個()提取結果
   * @param offset:匹配開始位置
   * @param source:原始字符串
   */
  this.replace(/(^\s+)|(\s+$)/g,function(rs,$1,$2,offset,source){
    //arguments中的每個元素對應一個參數
    console.log(arguments);
  });
};
 
" abcd ".trim();

輸出結果:

[" ", " ", undefined, 0, " abcd "] //第1次匹配結果
[" ", undefined, " ", 5, " abcd "] //第2次匹配結果

(2)提取瀏覽器url中的參數名和參數值,生成一個key/value的對象

function getUrlParamObj(){
  var obj = {};
  //獲取url的參數部分
  var params = window.location.search.substr(1);
  //[^&=]+ 表示不含&或=的連續字符,加上()就是提取對應字符串
  params.replace(/([^&=]+)=([^&=]*)/gi,function(rs,$1,$2){
    obj[$1] = $2;
  });
 
  return obj;
}

/([&=]+)=([&=]*)/gi 每次匹配到的都是一個完整key/value,形如 xxxx=xxx, 每當匹配到一個這樣的結果時就執行回調,並傳遞匹配到的key和value,對應到$1和$2

(3)在字符串指定位置插入新字符串

String.prototype.insetAt = function(str,offset){
 
  //使用RegExp()構造函數創建正則表達式
  var regx = new RegExp("(.{"+offset+"})");
 
  return this.replace(regx,"$1"+str);
};
 
"abcd".insetAt('xyz',2); //在b和c之間插入xyz
//結果 "abxyzcd"

當offset=2時,正則表達式爲:(^.{2}) .表示除\n之外的任意字符,後面加{2} 就是匹配以數字或字母組成的前兩個連續字符,加()就會將匹配到的結果提取出來,然後通過replace將匹配到的結果替換爲新的字符串,形如:結果=結果+str

(4) 將手機號12988886666轉化成129 8888 6666
複製代碼

function telFormat(tel){
 
  tel = String(tel);
 
  //方式一
  return tel.replace(/(\d{3})(\d{4})(\d{4})/,function (rs,$1,$2,$3){
    return $1+" "+$2+" "+$3
  });
 
  //方式二
  return tel.replace(/(\d{3})(\d{4})(\d{4})/,"$1 $2 $3");
}

(\d{3}\d{4}\d{4}) 可以匹配完整的手機號,並分別提取前3位、4-7位和8-11位,"$1 $2 $3" 是在三個結果集中間加空格組成新的字符串,然後替換完整的手機號。

  • 替換 XXYY---->YYXX
var str = "aabb";
var reg = /(\w)\1(\w)\2/g
console.log(str.replace(reg, "$2$2$1$1"));//bbaa   

var str = "aabb";
var reg = /(\w)\1(\w)\2/g
console.log(str.replace(reg, function($, $1, $2) {//replace的第二個參數也可以傳進去一個函數,但是如果要用子表達式,那麼就必須先傳$,然後再傳要用的子表達式。
    return $2 + $2 + $1 + $1;//子表達式用$取的時候要用加號把它們連接起來
}));//bbaa

  • 替換the-first-name-------->theFirstName
var reg = /-(\w)/g; //因爲要操作f和n讓它們變成大寫,所以要用子表達式的方式傳遞
var str = "the-first-name";
console.log(str.replace(reg, function($, $1){
    return $1.toUpperCase();
}))

3,字符串去重

var str = "aaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbccccccccccccc";
var reg = /(\w)\1*/g;
console.log(str.replace(reg, "$1"));// abc

4,實現從後往前每3個0打個小數點

var str = "10000000000";
var reg = /(?=(\B)(\d{3})+$)/g		
//從末尾開始,然後找3個數字連在一起的(\d{3})+$,然後用?=前面爲空就表示正向預查空的地方,
//最後添加(\B)是因爲如果0的個數爲偶數(假設100000000000),那麼就會出現.100.000.000.000這樣的情況,所以就要加上非單詞邊界
console.log(str.replace(reg, "."));//10.000.000.000
  • exec()方法

該方法是專門爲捕獲組而設計的,其接受一個參數,即要應用模式的字符串,然後返回包含第一個匹配項信息的數組;

在沒有匹配項的情況下返回null。返回的數組雖然是Array的實例,但是包含兩個額外的屬性:index和input

其中index表示匹配項在字符串中的位置,而input表示應用字符串表達式的字符串。

var text = "mom and dad and baby";
var pattern = /mom( and dad( and baby)?)?/gi;
var matches = pattern.exec(text);
console.log(matches.index); //0
console.log(matches.input); //mom and dad and baby
console.log(matches[0]);    //mom and dad and baby
console.log(matches[1]);    //and dad and baby
console.log(matches[2]);    //and baby

對於exec()方法而言,即使在模式中設置了全局標誌g,它每次也只是返回一個匹配項。

在不設置全局標誌的情況下,在同一個字符串上多次調用exec()方法將始終返回第一個匹配項的信息。

而在設置全局標誌的情況下,每次調用exec()則都會在字符串中繼續查找新匹配項,如下例子:

var text = "cat, bat, sat, fat";
var pattern1 = /.at/;

var matches = pattern1.exec(text);
console.log(matches.index); //0
console.log(matches[0]);  //cat
console.log(pattern1.lastIndex); //0

matches = pattern1.exec(text);
console.log(matches.index); //0
console.log(matches[0]);  //cat
console.log(pattern1.lastIndex); //0

var pattern2 = /.at/g;

var matches = pattern2.exec(text);
console.log(matches.index); //0
console.log(matches[0]);  //cat
console.log(pattern2.lastIndex); //3

var matches = pattern2.exec(text);
console.log(matches.index); //5
console.log(matches[0]);  //bat
console.log(pattern2.lastIndex); //8

在這裏插入圖片描述

IE的JavaScript實現lastIndex屬性上存在偏差,即使在非全局模式下,lastIndex屬性每次也都在變化。

5.貪婪匹配與非貪婪匹配

貪婪匹配:

貪婪匹配就是僅僅使用單個限定符:*,+,?,n{X},n{X,},n{X,Y}的匹配。
正則表達式一般趨向於最大長度匹配,也就是所謂的貪婪匹配。

非貪婪匹配(懶惰匹配):

非貪婪匹配就是在限定符*,+,?,n{X},n{X,},n{X,Y}之後再添加一個字符?,則儘可能少的重複字符“?”之前的限定符號的重複次數
非貪婪匹配就是匹配到結果就好,就少的匹配字符。

默認是貪婪模式;
在量詞後面直接加上一個問號?就是非貪婪模式。
在這裏插入圖片描述

var str = "aaaaaa";
var reg = /a{1,3}?/g;
console.log(str.match(reg));// ["a", "a", "a", "a", "a", "a"]
var str = "aaaaaa";
var reg = /a??/g;
console.log(str.match(reg));// ["", "", "", "", "", "", ""]
var str = "aaaaaa";
var reg = /a*?/g;
console.log(str.match(reg));// ["", "", "", "", "", "", ""]
var str = "aaa aaa";
var reg = / /g;
console.log(str.match(reg));// [" "]
6.正則表達式對象屬性

在這裏插入圖片描述
multiline 是一個只讀的布爾值,看這個正則表達式是否帶有修飾符m。

修飾符m,用以在多行模式中執行匹配,需要配合^ 和 $ 使用,使用^ 和 $ 除了匹配整個字符串的開始和結尾之外,還能匹配每行的開始和結尾。

主要用來匹配多行模式

var str="java\nJavaScript";
str.match(/^JavaScript/); //返回null
var str="java\nJavaScript";
str.match(/^JavaScript/m); //匹配到一個JavaScript
var reg=/JavaScript/;
reg.multiline; //返回false
var reg=/JavaScript/m;
reg.multiline; //返回true

lastIndex

lastIndex:是一個可讀/寫的整數,如果匹配模式中帶有g修飾符,這個屬性存儲在整個字符串中下一次檢索的開始位置,這個屬性會被exec( ) 和 test( ) 方法用到。

注:此屬性需要單獨說明,在exec和test方法下會用到並且改變正則對象的該屬性值。
source

source:是一個只讀的字符串,包含正則表達式的文本。

var reg = /Abc/;
reg.source; //返回 Abc

global

global:是一個只讀的布爾值,看這個正則表達式是否帶有修飾符g。
修飾符g,是全局匹配的意思,檢索字符串中所有的匹配。

var str = "JavaScript";
str.match(/JavaScript/); //只能匹配一個JavaScript 
var str = "JavaScript JavaScript";
str.match(/JavaScript/g); //能匹配兩個JavaScript 
var reg = /JavaScript/;
reg.global; //返回 false
var reg = /JavaScript/g;
reg.global; //返回 true

ignoreCase

ignoreCase:是一個只讀的布爾值,看這個正則表達式是否帶有修飾符i。
修飾符i,說明模式匹配是不區分大小寫的。

var reg = /JavaScript/;
reg.ignoreCase; //返回 false
var reg = /JavaScript/i;
reg.ignoreCase; //返回 true
var reg = /JavaScript/;
reg.test("javascript"); //返回 false
var reg = /JavaScript/i;
reg.test("javascript"); //返回 true
支持正則表達式的 String 對象的方法

在這裏插入圖片描述
字符串replace的侷限性就在於這,這就需要與正則表達式相結合完成替換

var str = "aa";
console.log(str.replace("a","b"));//ba

var reg = /a/				//沒有g它也是匹配到了一個就停止了。
var str = "aa";
console.log(str.replace(reg,"b"));//ba

var reg = /a/g
var str = "aa";
console.log(str.replace(reg,"b"));//bb
7.分組和反向引用一個子表達式裏面的內容

分組又稱爲子表達式,首先一個子表達式是用()表示的。

當一個正則表達式被分組之後,每一個組被自動賦予一個組號,該組號可以代表該組的 表達式。

1.匹配XX的片段

var str = "aaaa";
var reg = /(a)\1/g				//\1就表示反向引用第一個子表達式(a)的內容
console.log(str.match(reg));//["aa", "aa"]

2.匹配XXXX的片段

var str = "aaaabbbb";			//\1\1\1就表示三次反向引用第一個子表達式(\w)的內容
var reg = /(\w)\1\1\1/g			
console.log(str.match(reg));// ["aaaa", "bbbb"]

3,匹配XXXX的片段

var str = "aaaabbbb";
var reg = /(\w)\1\1\1/			//沒有g全局搜索就會匹配到了之後就會停止
console.log(str.match(reg));//["aaaa", "a", index: 0, input: "aaaabbbb", groups: undefined]
console.log(reg.exec(str));//["aaaa", "a", index: 0, input: "aaaabbbb", groups: undefined]

var str = "aaaabbbb";
var reg = /(\w)\1\1\1/g
console.log(str.match(reg)); //["aaaa", "bbbb"]
console.log(reg.exec(str));//["aaaa", "a", index: 0, input: "aaaabbbb", groups: undefined]

4.匹配XXYY的形式

var str = "aabbbbcdfsf";
var reg = /(\w)\1(\w)\2/g		//\1反向引用第一個子表達式,那麼\2就表示反向引用第二個子表達式,還可以有\3,\4,\5........表示反向引用第3,4,5個子表達式的內容
console.log(str.match(reg));// ["aabb"]

var str = "aabbbbcdkkoo";
var reg = /(\w)\1(\w)\2/g
console.log(str.match(reg));//  ["aabb", "kkoo"]

var str = "aabbbbcdfsf";
var reg = /(\w)\1(\w)\2/		//沒有全局搜索用str.match()就會出現返回子表達式的內容還有一些其他的信息。
console.log(str.match(reg));// ["aabb", "a", "b", index: 0, input: "aabbbbcdfsf", groups: undefined]

沒有全局搜索g用str.match()就會出現返回子表達式的內容還有一些其他的信息。
無論有沒有g用reg.exec()都會出現返回子表達式的內容還有一些其他的信息,因爲這是exec()方法 的特性。

分組不但可以使用數字作爲組號,而且還可以使用自定義名稱作爲組號。

1.以下兩個正則表達式都是將分組後的子表達式w+命名爲“word”.
(?\w+)
(? ‘word’ \w+)

2.因此,正則表達式\b(\w+)\b\s+\1\b和以下正則表達式等價,它們都匹配重複出現的單詞。
\b(?\W+)\b\s+\k\b

3.以下正則表達式和正則表達式\b\w*(\w+)\1\b等價,它也是匹配以兩個重複字符結尾的單詞。
\b\w* (?\w+)\k\b

4,分組子表達式(?)將元字符括在其中,並強制正則表達式引擎記住該子表達式匹配,同時使用“name”對該匹配進行命名。

反向引用\k使引擎對當前字符和以名稱“name”存儲的先前匹配字符進行比較,從而匹配具有重複字符的字符串。
在這裏插入圖片描述

8.優先級順序

在這裏插入圖片描述

9.斷言

零寬斷言
匹配寬度爲零,滿足一定的條件/斷言。

零寬斷言用於查找在某些內容(但並不包括這些內容)之前或之後的東西,也就是說它們像\b,^,$那樣用於指定一個位置,這個位置應該滿足一定的條件(即斷言),因此它們也被稱爲零寬斷言。

斷言用來聲明一個應該爲真的事實。正則表達式中只有當斷言爲真時纔會繼續進行匹配

  • 先行斷言(零寬度正預測先行斷言)

         表達式:(?=表達式)
         表示匹配表達式前面的位置
         先行斷言的執行步驟是這樣的先從要匹配的字符串中的最右端找到第一個ing(也就是先行斷言中的表達式)然後 再匹配其前面的表達式,若無法匹配則繼續查找第二個ing 再匹配第二個 ing前面的字符串,若能匹配 則匹配
         .*(?=d) 可c以匹配abcdefghi 中的abc
    
  • 後發斷言(零寬度正回顧後發斷言)

         表達式: (?<=表達式)
         表示匹配表達式後面的位置
         後發斷言跟先行斷言恰恰相反 它的執行步驟是這樣的:
         先從要匹配的字符串中的最左端找到第一個abc(也就是先行斷言中的表達式)然後 再匹配其後面的表達式,
         若無法匹配則繼續查找第二個abc 再匹配第二個abc後面的字符串,若能匹配 則匹配
         
         例如(?<=abc).* 可以匹配abcdefg中的defg
    
  • 負向斷言

         負向零寬先行斷言 :(?!表達式)
         負向零寬後發斷言:(?<!表達式)
         負向零寬斷言 (?!表達式) 也是匹配一個零寬度的位置,不過這個位置的“斷言”取表達式的反值,
         例如 (?!表達式) 表示 表達式 前面的位置,如果 表達式 不成立 ,匹配這個位置;
         如果 表達式 成立,則不匹配:同樣,負向零寬斷言也有“先行”和“後發”兩種,負向零寬後發斷言爲 (?<!表達式)
    

在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章