ECMAScript正則表達式

我只是文檔搬運工,總結得很差,不免疏漏,如有錯誤請幫我指出,謝謝。ide

1. 如何建立

  • 使用RegExp構造函數
  • 使用正則表達式字面量

使用字面量定義的任何正則表達式均可以使用構造函數來構建函數

正則表達式是構成搜索模式(search pattern)的字符序列,匹配字符串中字符組合的模式。至關因而一個描述或者一個檢索規則,針對你想要操做的內容。post

在JS中 RegExp 是對象,有 test 方法和 exec 方法,同時還有字符串的 match、replace、search、split、matchAll 方法可用。可經過 正則表達式字面量 直接建立或者 new RegExp 對象。性能

mdn中說道:腳本加載後,正則表達式字面量就會被編譯。當正則表達式保持不變時,使用字面量可得到更好的性能。在腳本運行的過程當中,用構造函數建立的正則表達式會被編譯。若正則表達式發生該改變,或者須要從用戶輸入等來源中動態的產生,就須要使用構造函數來建立正則表達式。在須要改變正則表達式是可使用compile從新編譯。

爲何要從新編譯呢?我發現測試時即使不從新編譯輸出結果也是同樣的,我在掘金找到一份回答:https://juejin.im/post/5b6adc... 也許有用 大意爲:若是指定的正則表達式須要屢次重複使用,那麼編譯正則表達式將會提升代碼的執行效率,不過若是僅僅執行一次或者少數幾回,那麼將不會有明顯的效果,compile提升了正則表達式的適應性!測試

2. 如何編寫

格式:/pattern/flags;

2.1. 肯定字符串

直接使用 /str/便可

2.2. 不肯定字符串

2.2.1. 斷言

2.2.1.1. Assertions

表示一個匹配在某些條件下發生。斷言包含先行斷言、後行斷言和條件表達式。

const text = 'A quick fox';
    const regexpLastWord = /\w+$/;
    console.log(text.match(regexpLastWord));
    // expected output: Array ["fox"]
    const regexpWords = /\b\w+\b/g; // \b表單詞邊界
    console.log(text.match(regexpWords));
    // expected output: Array ["A", "quick", "fox"]
    const regexpFoxQuality = /\w+(?= fox)/; // 匹配前面的\w+僅當\w+後面跟着fox時,這種叫作先行斷言。
    console.log(text.match(regexpFoxQuality));
    // expected output: Array ["quick"]
Characters Meaning
^ Matches the beginning of input
$ Matches the end of input
\b Matches a word boundary
\B Matches a non-word boundary
x(?=y) Matches "x" only if "x" is followed by "y"
x(?!y) Matches "x" only if "x" is not followed by "y"
(?<=y)x Matches "x" only if "x" is preceded by "y"
(?<!y)x Matches "x" only if "x" is not preceded by "y"
attention:(different meaning in the start of group)

2.2.1.2. 附加:Groups and ranges

Characters Meaning
`x y` Matches either "x" or "y"
[xyz] [a-c] A character set.
[^xyz] [^a-c] A negated or complemented character set
(x) Matches x and remembers the match
\n Where "n" is a positive integer
(?<Name>x) Named capturing group
(?:x) Non-capturing group
attention: (?<Name>x) Matches "x" and stores it on the groups property of the returned matches under the name specified by <Name>

2.2.2. 邊界(Boundaries)

表示行和單詞的開始和結尾。

2.2.3. 字符類別(Character Classes)

區分不一樣類型的字符,例如區分字母和數字。

2.2.4. 組和範圍(Groups and Ranges)

表示表達式字符的分組和範圍。

2.2.5. 量詞(Quantifiers)

表示匹配的字符或表達式的數量。

2.2.6. Unicode 屬性轉義(Unicode Property Escapes)

基於 unicode 字符屬性區分字符。例如大寫和小寫字母、數學符號和標點。

2.3. 特殊字符

我看了 w3school.com.cn 的解釋和 MDN 的解釋,對比一下,建議看 MDN 正則表達式中特殊字符的含義

量詞 描述
n+ 匹配前面的模式 n 1 次或屢次
n* 匹配前面的模式 n 0 或屢次
n? 匹配前面的模式 n 0 或 1 次
n{X} x 是一個正整數。前面的模式 n 連續出現 x 次時匹配
n{X,Y} 匹配包含 X 至 Y 個 n 的序列的字符串。
n{X,} 匹配包含至少 X 個 n 的序列的字符串。
n$ 匹配任何結尾爲 n 的字符串。
^n 匹配任何開頭爲 n 的字符串。
?=n 匹配任何其後緊接指定字符串 n 的字符串。
?!n 匹配任何其後沒有緊接指定字符串 n 的字符串。
`x\ y` 匹配 x 或 y

2.4. 修飾符

2.4.1. syntax

var re = /pattern/flags; or var re = new RegExp('pattern', 'flags');

flag 意義 對應的屬性
i 不區分大小寫 RegExp.prototype.global
g 全局搜索 RegExp.prototype.ignoreCase
m 多行搜索 RegExp.prototype.multiline
s 容許 . 匹配換行符 (在 ES2018 添加,Firefox不支持) RegExp.prototype.dotAll
u 使用unicode碼的模式進行匹配 RegExp.prototype.unicod
y 執行 粘性 搜索,匹配從目標字符串的當前位置開始,可使用y標誌 RegExp.prototype.sticky

2.4.2. 附加

  1. 標誌是一個正則表達式的一部分,在正則表達式建立以後,它們在接下來的時間將不能添加或刪除。
  2. 使用.exec()方法時,與'g'標誌關聯的行爲是不一樣的。在一開始講 建立 的時候就提過exec是RegExp的方法,而match是String的方法,這時候來看爲何兩個方法在沒有g標誌時看似是同樣的,爲何有了g就不同呢?

exec()的狀況下,正則表達式是 擁有該方法 的正則表達式,其中字符串是參數;在.match()的狀況下,字符串類(or data type)擁有該方法,而正則表達式只是一個參數。對比str.match(reg)reg.exec(str) , 'g'標誌與exec()方法一塊兒使用由於lastIndex參數會迭代進行,這在後面講exec方法有詳細介紹。

  1. 其中的m表明的多行匹配如何使用?

m標誌用於指定多行輸入字符串應該被視爲多個行。若是使用m標誌,^和$匹配的開始或結束輸入字符串中的每一行,而不是整個字符串的開始或結束。

var reg = new RegExp("^.", "gm");
    var str = "hui \nhello \nfuck!";
    console.log(str.match(reg)); //(3) ["h", "h", "f"]

2.4.3. 例子

var names = "Orange Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ";
    var output = ["---------- Original String\n", names + "\n"];
    // 此時output = ["---------- Original String↵", "Orange Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ↵"]
    var pattern = /\s*;\s*/;
    var nameList = names.split(pattern);
    // 此時nameList = ["Orange Trump", "Fred Barney", "Helen Rigby", "Bill Abel", "Chris Hand "]
    pattern = /(\w+)\s+(\w+)/;
    var bySurnameList = [];
    output.push("---------- After Split by Regular Expression");
    // 此時output = ["---------- Original String↵", "Orange Trump ;Fred Barney; Helen Rigby ; Bill Abel ; Chris Hand ↵", "---------- After Split by Regular Expression"]
    var i, len;
    for (i = 0, len = nameList.length; i < len; i++) {
        output.push(nameList[i]);
        bySurnameList[i] = nameList[i].replace(pattern, "$2, $1");
        console.log("xixixi:" + bySurnameList[i]);
    }

    // 輸出新的數組
    output.push("---------- Names Reversed");
    for (i = 0, len = bySurnameList.length; i < len; i++) {
        output.push(bySurnameList[i]);
    }

    // 根據姓來排序,而後輸出排序後的數組。
    bySurnameList.sort();
    output.push("---------- Sorted");
    for (i = 0, len = bySurnameList.length; i < len; i++) {
        output.push(bySurnameList[i]);
    }

    output.push("---------- End");
 
    console.log(output.join("\n"));

2.5. RegExp 對象方法

2.5.1. RegExpObject.compile(regexp,modifier)

用於在腳本執行過程當中編譯正則表達式,也可用於改變或從新編譯正則表達式。modifier只有i、g

var str = "Every man in the world! Every woman on earth!";
    console.log(str);
    patt = /man/g;
    str2 = str.replace(patt, "person");
    console.log(str2);
    console.log(patt);

    patt = /(wo)?man/g;
    console.log(patt);

    patt.compile(patt); //改變正則表達式以後從新編譯
    // 爲何要從新編譯呢?我發現測試時即使不從新編譯輸出結果也是同樣的
    // 我在掘金找到一份回答:https://juejin.im/post/5b6adc7ee51d4534b8587560#heading-22
    // 大意爲:若是指定的正則表達式須要屢次重複使用,那麼編譯正則表達式將會提升代碼的執行效率,不過若是僅僅執行一次或者少數幾回,那麼將不會有明顯的效果,compile提升了正則表達式的適應性!
    console.log(patt);

    str2 = str.replace(patt, "person");
    console.log(str2);

2.5.2. RegExpObject.exec(string)

經過模式搜索字符串並返回已找到的文本,返回的是一個數組,但即便字符串中有多個匹配的文本時也只會返回第一個匹配到的結果。

exec更加靈活也更加複雜,若是 exec() 找到了匹配的文本,則返回一個結果數組。不然,返回 null。此數組的第 0 個元素是與正則表達式相匹配的文本,第 1 個元素是與 RegExpObject 的第 1 個子表達式相匹配的文本(若是有的話),第 2 個元素是與 RegExpObject 的第 2 個子表達式相匹配的文本(若是有的話),以此類推。除了數組元素和 length 屬性以外,exec() 方法還返回兩個屬性。index 屬性聲明的是匹配文本的第一個字符的位置。input 屬性則存放的是被檢索的字符串 string。咱們能夠看得出,在調用非全局的 RegExp 對象的 exec() 方法時,返回的數組與調用方法 String.match() 返回的數組是相同的。

可是,當 RegExpObject 是一個全局正則表達式時,exec() 的行爲就稍微複雜一些。它會在 RegExpObject 的 lastIndex 屬性指定的字符處開始檢索字符串 string。當 exec() 找到了與表達式相匹配的文本時,在匹配後,它將把 RegExpObject 的 lastIndex 屬性設置成匹配到的文本中的最後一個字符的下一個位置,在下面的例子中也就是每次匹配到的hui中的i字符對應的下一個位置。可知經過反覆調用 exec() 方法可遍歷字符串中的全部匹配文本。當 exec() 再也找不到匹配的文本時,它將返回 null,並把 lastIndex 屬性重置爲 0。

var reg = new RegExp(/hui/ig);
    var str = 'hui hui hui Like Summer';
    console.log(reg.lastIndex); //0
    console.log(reg.exec(str));//["hui", index: 0, input: "hui hui hui Like Summer", groups: undefined]
    // 匹配的的文本的最後一個字符的下一位即2的下一位爲3
    console.log(reg.lastIndex); //3
    console.log(reg.exec(str));//["hui", index: 4, input: "hui hui hui Like Summer", groups: undefined]
    console.log(reg.lastIndex); //7
    console.log(reg.exec(str));//["hui", index: 8, input: "hui hui hui Like Summer", groups: undefined]
    console.log(reg.lastIndex); //11
    console.log(reg.exec(str));//null
    console.log(reg.lastIndex);//0
var reg = /\w+\s/g;
    var str = "fee fi fo fum";
    var xArray;
    while (xArray = reg.exec(str)) console.log(xArray);
    // ["fee ", index: 0, input: "fee fi fo fum"]
    // ["fi ", index: 4, input: "fee fi fo fum"]
    // ["fo ", index: 7, input: "fee fi fo fum"]

若是在reg匹配過以後要換一個字符串從新進行匹配,那麼須要手動把reg.lastIndex設置爲0,不然回像下面這樣明明存在卻匹配不出來。

var reg = new RegExp(/hui/ig);
    var str = 'hui hui hui Like Summer';
    console.log("lastIndex:" + reg.lastIndex); //0
    console.log(reg.exec(str));
    console.log("lastIndex:" + reg.lastIndex); //3
    console.log(reg.exec('hui Like Summer'));

同時exec相比於match返回的信息要詳細的多。

var reg = new RegExp(/hui/ig);
    var str = '  HuiDT hui hui hui Like Summer';
    console.log(reg.exec('  HuiDT hui hui hui Like Summer'));
    console.log(reg.exec(str));
    console.log(/hui/ig.exec('  HuiDT hui hui hui Like Summer'));
    console.log(/hui/ig.exec(str));

2.5.3. test()

看字符串中是否存在正則表達式(經過模式來搜索字符串),返回 true 或 false。

var reg = /hui/;
    var str = '  huiDT Like Summer';
    console.log(reg.test('huiDT Like Summer'));
    console.log(reg.test(str));
    console.log(/hui/.test('huiDT Like Summer'));
    console.log(/hui/.test(str));

2.6. RegExp實例屬性

RegExp的每一個實例都具備如下屬性,經過這些屬性能夠獲得一些信息。

  • global:布爾值,表示是否設置了g標誌。
  • ignoreCase:布爾值,表示是否設置了i標誌。
  • multiline:整數,表示開始搜索寫一個匹配項的字符位置,從0算起。
  • lastIndex:布爾值,表示是否設置了m標誌。
  • source:正則表達式的字符串表示,按照字面量形式而非傳入構造函數中的字符串模式返回。

2.7. RegExp構造函數屬性

RegExp構造函數包含一些屬性,適用於做用域中的全部正則表達式,這些屬性分別有一個長屬性和短屬性名。

長屬性名 短屬性名 說明
input $_ 最近一次要匹配的字符串
lastMatch $& 最近一次的匹配項
lastParen $+ 最近一次匹配的捕獲組
leftContext $` input字符串中lastMatch以前的文本
multiline $* 布爾值,表示是否全部表達式都是用多行模式
rightContext $' Input字符串中lastMatch以後的文本

2.8. 支持正則表達式的 String 對象的方法

  1. seaech():接受字符串做爲搜索參數。字符串參數將被轉換爲正則表達式,返回結果是模式第一次出現的位置。
var reg = /hui/i;
    var str = 'DT hui Like Summer';
    console.log(str.search(reg)); //3
    console.log(str.search("hui")); //3
    console.log(str.search(/hui/i)); //3
    console.log('DT hui Like Summer'.search(reg)); //3
    console.log('DT hui Like Summer'.search("hui")); //3
    console.log('DT hui Like Summer'.search(/hui/i)); //3
  1. replace:替換與正則表達式匹配的子串。
var reg = /hui/i;
    var str = 'DT hui Like Summer';
    var str1 = '會';
    console.log(str.replace('DT', '會'));
    console.log(str.replace(/hui/, '會'));
    console.log(str.replace(/DT/, str1));
    console.log(str.replace(reg, str1));
    console.log('DT  DT hui Like Summer'.replace(/DT/g, '會'));
  1. match:找到一個或多個正則表達式的匹配。
var reg = new RegExp("hui", 'ig');
    var str = "Huihui Like Summer";
    console.log(str.match(reg));

正則表達式由普通字符和特殊字符(元字符)組成,其中普通字符包括非打印字符

  1. split:把字符串分割爲字符串數組。

2.9. 方括號

表示範圍,用來查找指定範圍內的字符

  1. [abc]找方括號中出現的字符,即給定集合中出現的字符
var reg = /[abc]/ig;
    var str = "A a b d hui";
    console.log(str.match(reg)); //["A", "a", "b"]
  1. 1找方括號中沒有出現的全部字符,即給定集合以外的字符
var reg = /[^abc]/ig;
    var str = "A a b d hui";
    console.log(str.match(reg)); // [" ", " ", " ", "d", " ", "h", "u", "i"]
  1. [0-9]:查找任何從 0 至 9 的數字。
  2. [a-z]:查找任何從小寫 a 到小寫 z 的字符。
  3. [A-Z]:查找任何從大寫 A 到大寫 Z 的字符。
  4. [A-z]:查找任何從大寫 A 到小寫 z 的字符。
  5. (red|blue|green):查找任何指定的選項。
var str = "abchui";
    console.log(str.match(/[|a|b|c]/ig)); //["a", "b", "c"]
    console.log(str.match(/[^|a|b|c]/ig)); //["h", "u", "i"]
    console.log(str.match(/(^a|b|c)/ig)); //["a", "b", "c"]
    console.log(str.match(/(a|hui)/ig)); //["a", "hui"]

2.10. 元字符

元字符指擁有特殊含義的字符

在試圖匹配它們時要求轉義。

特殊字符 描述
. 查找單個字符,除了換行和行結束符。
\w 查找單詞字符(除符號、空格)
\W 查找非單詞字符。
\d 查找數字。
\D 查找非數字字符。
\s 查找空白字符。
\S 查找非空白字符。
\b 匹配單詞邊界。
\B 匹配非單詞邊界。
\0 查找 NUL 字符。
\n 查找換行符。
\f 查找換頁符。
\r 查找回車符。
\t 查找製表符。
\v 查找垂直製表符。
\xxx 查找以八進制數 xxx 規定的字符。
\xdd 查找以十六進制數 dd 規定的字符。
\uxxxx 查找以十六進制數 xxxx 規定的 Unicode 字符。

【例】

var str = "Like's 520";
    var reg1 = /./ig;
    console.log(str.match(reg1)); // ["L", "i", "k", "e", "'", "s", " ", "5", "2", "0"]
    var reg2 = /\w/ig;
    console.log(str.match(reg2)); //["L", "i", "k", "e", "s", "5", "2", "0"]
    var reg3 = /\W/ig;
    console.log(str.match(reg3)); //["'", " "]
    var reg4 = /\d/ig;
    console.log(str.match(reg4)); //["5", "2", "0"]
    var reg5 = /\D/ig;
    console.log(str.match(reg5)); //["L", "i", "k", "e", "'", "s", " "]
    var reg6 = /\s/ig;
    console.log(str.match(reg6)); //[" "]
    var reg7 = /\S/ig;
    console.log(str.match(reg7)); //["L", "i", "k", "e", "'", "s", "5", "2", "0"]
    var reg8 = /\b/ig; //單詞邊界,找單詞旁邊的空格
    console.log(str.match(reg8)); //(6) ["", "", "", "", "", ""]

    var reg9 = /\B/ig; //非單詞邊界,找連續單詞之間的間隔有幾個
    console.log(str.match(reg9)); //(5) ["", "", "", "", ""]
    console.log("1234567".match(reg9)); //(6) ["", "", "", "", "", ""]

    str = "Like's hui A ቐ W \0 \n \f \r \t \v  0b10 070 0xaa ";
    var reg10 = /\0/ig;
    console.log(str.match(reg10));
    var reg11 = /\n/ig;
    console.log(str.match(reg11));
    var reg12 = /\f/ig;
    console.log(str.match(reg12));
    var reg13 = /\r/ig;
    console.log(str.match(reg13));
    var reg14 = /\t/ig;
    console.log(str.match(reg14));
    var reg15 = /\v/ig;
    console.log(str.match(reg15)); //[""]
    var reg16 = /\150/g; // 找八進制數
    console.log(str.match(reg16));
    var reg17 = /\151/g; //找八進制數
    console.log(str.match(reg17));
    console.log(str.match(/\x57/g)); //找十六進制數
    var reg18 = /\u0041/g; //查找以十六進制數 xxxx 規定的 Unicode 字符
    console.log(str.match(reg18));
    console.log(str.match(/\u1250/));
( [  { \ ^ $ | ) ? * + . ] }

用法參考:https://developer.mozilla.org...

元字符 描述
$ 匹配輸入字符串的結尾位置。若是設置了 RegExp 對象的 Multiline 屬性,則 $ 也匹配 '\n' 或 '\r'。要匹配 $ 字符自己,請使用 \$
( ) 標記一個子表達式的開始和結束位置。子表達式能夠獲取供之後使用。要匹配這些字符,請使用 \(\)
* 匹配前面的子表達式零次或屢次。要匹配 * 字符,請使用 \*
+ 匹配前面的子表達式一次或屢次。要匹配 + 字符,請使用 \+
. 匹配除換行符 \n以外的任何單字符。要匹配 .,請使用 \
[ 標記一箇中括號表達式的開始。要匹配 [,請使用 \[
? 匹配前面的子表達式零次或一次,或指明一個非貪婪限定符。要匹配 ? 字符,請使用
\ 將下一個字符標記爲或特殊字符、或原義字符、或向後引用、或八進制轉義符。例如, 'n' 匹配字符 'n'。'\n' 匹配換行符。序列 '\\' 匹配 "\",而 '\(' 則匹配 "("。
^ 匹配輸入字符串的開始位置,除非在方括號表達式中使用,此時它表示不接受該字符集合。要匹配 ^ 字符自己,請使用 \^
{ 標記限定符表達式的開始。要匹配 {,請使用 \{
`\ ` 指明兩項之間的一個選擇。要匹配 `\ ,請使用 `\

2.11. 非打印字符

字符 描述
\cx 匹配由x指明的控制字符。例如, \cM 匹配一個 Control-M 或回車符。x 的值必須爲 A-Z 或 a-z 之一。不然,將 c 視爲一個原義的 'c' 字符。
\f 匹配一個換頁符。等價於 \x0c\cL
\n 匹配一個換行符。等價於 \x0a\cJ
\r 匹配一個回車符。等價於 \x0d\cM
\s 匹配任何空白字符,包括空格、製表符、換頁符等等。等價於 [ \f\n\r\t\v]
\S 匹配任何非空白字符。等價於 [^ \f\n\r\t\v]
\t 匹配一個製表符。等價於 \x09\cI
\v 匹配一個垂直製表符。等價於 \x0b\cK

2.12. 運算符優先級

2.13. 匹配規則

var str = "hui hello    fuck! Orange Trump";
    str1 = str.replace(/(\w+)\s+(\w+)/g, "$2,$1");
    console.log(str1); //hello,hui    fuck! Trump,Orange

3. 侷限性

ECMAScript缺乏某些語言所支持的該機正則表達式特性(特別是perl)。


  1. abc
相關文章
相關標籤/搜索
本站公眾號
   歡迎關注本站公眾號,獲取更多信息