关于javascript:ECMAScript正则表达式

42次阅读

共计 11799 个字符,预计需要花费 30 分钟才能阅读完成。

  • 1. 如何创立
  • 2. 如何编写

    • 2.1. 确定字符串
    • 2.2. 不确定字符串

      • 2.2.1. 断言

        • 2.2.1.1. Assertions
        • 2.2.1.2. 附加:Groups and ranges
      • 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)
    • 2.3. 特殊字符
    • 2.4. 修饰符

      • 2.4.1. syntax
      • 2.4.2. 附加
      • 2.4.3. 例子
    • 2.5. RegExp 对象办法

      • 2.5.1. RegExpObject.compile(regexp,modifier)
      • 2.5.2. RegExpObject.exec(string)
      • 2.5.3. test()
    • 2.6. RegExp 实例属性
    • 2.7. RegExp 构造函数属性
    • 2.8. 反对正则表达式的 String 对象的办法
    • 2.9. 方括号
    • 2.10. 元字符
    • 2.11. 非打印字符
    • 2.12. 运算符优先级
    • 2.13. 匹配规定
  • 3. 局限性

我只是文档搬运工,总结得不好,不免疏漏,若有谬误请帮我指出,谢谢。

1. 如何创立

  • 应用 RegExp 构造函数
  • 应用正则表达式字面量

应用字面量定义的任何正则表达式都能够应用构造函数来构建

正则表达式是形成搜寻模式(search pattern)的字符序列,匹配字符串中字符组合的模式。相当于是一个形容或者一个检索规定,针对你想要操作的内容。

在 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 ↩

正文完
 0