正则表达式

参考:

  1. https://www.jb51.net/tools/zhengze.html
  2. https://docs.microsoft.com/zh-cn/dotnet/standard/base-types/regular-expression-language-quick-reference

Js 中正则表达式的定义

  1. 构造函数方式
  1. var reg = new RegExp('a','gi')
  2. var str = '012a'
  3. console.log(str.search(reg))
  • 第一个参数是正则的内容,第二个参数是修饰符;
  • 修饰符通常有三种,i,g,m;
  • i (IgnoreCase)表示的含义是忽略大小写进行匹配;
  • g ()表示全局匹配即匹配到第一个之后不停止继续匹配;
  • m (Multiline)表示多行匹配即遇到换行后不停止匹配继续直到被匹配字符串结束。
  1. 字面量方式
  1. var reg = /a/gi

Js 中能使用正则表达式的方法有哪些?

String

  1. replace

该方法用来将字符串中的某些子串替换为需要的内容,接受两个参数,第一个参数可以为正则或者子字符串,表示匹配需要被替换的内容,第二个参数为被替换的新的子字符串。如果声明为全局匹配则会替换所有结果,否则只替换第一个匹配到的结果。

  1. 'abcabc'.replace(/a/,'A')
  2. 'abcabc'.replace(/a/g,'A')
  3. 'abcabc'.replace(/a/gi,'S')
  1. search

用来查找第一次匹配的子字符串的位置,如果找到就返回一个 number 类型的 index 值,否则返回-1,它返回的只是第一次匹配的位置。

  1. console.log('hello world!'.search(/l/g))
  1. split

该方法主要用来将一个字符串拆分成一个数组,它接受一个正则或者子字符(串)作为参数,返回一个数组

  1. let str = 'a|b|c'
  2. console.log(str.split('|'))
  3. let str2 = 'a|b c\*\*d'
  4. let arr = str2.split(/\||\s+|\*\*/)
  5. console.log(arr)
  1. match

该方法接受一个正则作为参数,用来匹配一个字符串,它的输出结果在不是全局匹配的情况下和 exec 方法的结果一致即一个数组并带有额外的属性,如果采用全局匹配,则不返回任何和其被匹配字符串相关的信息,只返回匹配的结果。

  1. var str = "hello javascript!"
  2. var reg1 = /a/
  3. console.log(str.match(reg1))
  4. var reg2 = /a/g
  5. console.log(str.match(reg2))
  6. // 小括号问题
  7. var str2 = 'abcabc'
  8. var reg3 = /(b)c/
  9. console.log(str2.match(reg3))
  10. var reg4 = /(b)c/g
  11. console.log(str2.match(reg4))

RegExp

  1. test

该方法用来测试某个字符串是否与正则匹配,匹配就返回 true,否则返回 false。

  1. var reg = /abc/
  2. var str = 'abc'
  3. console.log(reg.test(str))
  1. exec

该方法属于一个比较复杂的方法,它接受一个字符串,返回的是一个数组,数组中第 0 个元素是匹配的子字符串,第二个元素是正则中的第一个子分组匹配的结果(如果有子分组,即正则中存在用圆括号括起来的分组),第三个是正则中第二个子分组匹配的结果(如果有第二个子分组)…以此类推,如果没有正则子分组,那么该数组长度仅仅为 1,就是匹配到的那个子字符串。同时,返回的这个数组同时还是一个对象,它拥有两个属性,分别为 index 表示当前匹配到的子字符串所处的位置,input 属性表示被匹配的原始字符串。最后,该方法中的正则对象如果不是全局匹配,即没有 g 修饰符,则每次调用只会从字符串开头处匹配第一个结果,且每次调用结果都是一样的。只有指定为全局匹配,才能够按照从左往右依次去匹配,每次调用匹配一个结果,正则对象的 lastIndex 属性前进到本次匹配的末尾位置,下回再调用的时候,会从 lastIndex 处开始匹配而不是从头匹配

  1. var reg = /abc/g
  2. var str = 'abcdefgabcefg'
  3. var arr = reg.exec(str)
  4. while(arr){
  5. console.log(arr)
  6. arr = reg.exec(str)
  7. }
  1. compile

该方法的作用是能够对正则表达式进行编译,被编译过的正则在使用的时候效率会更高,适合于对一个正则多次调用的情况下,如果对一个正则只使用一两次,那么该方法没有特别显著的效应。

接受的参数也是一个正则。

  1. var reg=/[abc]/gi;
  2. console.log(reg.test('a'));
  3. reg=/[cde]/gi;
  4. console.log(reg.test('a'));
  5. reg.compile(reg);
  6. console.log(reg.test('a'));

被编译的正则和没有编译的正则在测试结果上没有任何区别,只是多次调用的效率上会更高一些。

正则工具

RegexBuddy
使用手册

  • mac 环境

正则入门

正则表达式由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义

元字符

常用元字符

元字符 描述
. 匹配除换行符(“\n”和”\r”)以外的任意字符
\w 匹配字母或数字或下划线或汉字
\s 匹配任意的空白符
\d 匹配数字
\b 匹配单词的开始或结束
^ 匹配字符串的开始
$ 匹配字符串的结束
\ 将下一个字符标记符、或一个向后引用、或一个八进制转义符。例如,“\\n”匹配\n。“\n”匹配换行符。序列“\\”匹配“\”而“\(”则匹配“(”。即相当于多种编程语言中都有的“转义字符”的概念。

限定元字符

元字符 描述
* 匹配任意次
+ 匹配至少一次或更多次
匹配零次或一次
{n} 匹配 n 次
{n,} 匹配 n 次或更多次
{n,m} 匹配 n 次到 m 次

字符集

元字符 描述
a-z 字符范围。匹配指定范围内的任意字符。例如,“[a-z]”可以匹配“a”到“z”范围内的任意小写字母字符
1-9 数字范围,匹配指定范围内的任意数字。例如,”1-9”可以匹配 1 到 9 范围内的任意数字
x 匹配 x

分支分组元字符

元字符 描述
() 将( 和 ) 之间的表达式定义为“组”(group),并且将匹配这个表达式的字符保存到一个临时区域(一个正则表达式中最多可以保存 9 个),它们可以用 \1 到\9 的符号来引用
| 将两个匹配条件进行逻辑“或”(Or)运算。例如正则表达式(him | her) 匹配”it belongs to him”和”it belongs to her”,但是不能匹配”it belongs to them.”。

反义

元字符 描述
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[^x] 配除了 x 以外的任意字符
[^aeiou] 匹配除了 aeiou 这几个字母以外的任意字符

后向引用

元字符 描述
(exp) 匹配 exp,并捕获文本到自动命名的组里
(?exp) 匹配 exp,并捕获文本到名称为 name 的组里,也可以写成(?’name’exp)
(?:exp) 匹配 exp,不捕获匹配的文本,也不给此分组分配组号

零宽断言

元字符 描述
(?=exp) 匹配 exp 前面的位置
(?<=exp) 匹配 exp 后面的位置
(?!exp) 匹配后面跟的不是 exp 的位置
(?<!exp) 匹配前面不是 exp 的位置

负向零宽断言

注释

(?#comment)

贪婪与懒惰

元字符 描述
*? 重复任意次,但尽可能少重复
+? 重复 1 次或更多次,但尽可能少重复
?? 重复 0 次或 1 次,但尽可能少重复
{n,m}? 重复 n 到 m 次,但尽可能少重复
{n,}? 重复 n 次以上,但尽可能少重复

平衡组/递归匹配

有时我们需要匹配像( 100 * ( 50 + 15 ) )这样的可嵌套的层次性结构,这时简单地使用(.+)则只会匹配到最左边的左括号和最右边的右括号之间的内容(这里我们讨论的是贪婪模式,懒惰模式也有下面的问题)。假如原来的字符串里的左括号和右括号出现的次数不相等,比如( 5 / ( 3 + 2 ) ) ),那我们的匹配结果里两者的个数也不会相等。有没有办法在这样的字符串里匹配到最长的,配对的括号之间的内容呢?

为了避免(和(把你的大脑彻底搞糊涂,我们还是用尖括号代替圆括号吧。现在我们的问题变成了如何把 xx yy 这样的字符串里,最长的配对的尖括号内的内容捕获出来?

这里需要用到以下的语法构造:

  • (?’group’) 把捕获的内容命名为 group,并压入堆栈(Stack)
  • (?’-group’) 从堆栈上弹出最后压入堆栈的名为 group 的捕获内容,如果堆栈本来为空,则本分组的匹配失败
  • (?(group)yes|no) 如果堆栈上存在以名为 group 的捕获内容的话,继续匹配 yes 部分的表达式,否则继续匹配 no 部分
  • (?!) 零宽负向先行断言,由于没有后缀表达式,试图匹配总是失败

其它元字符