手把手教你认识前端的正则表达式

2022-03-07 14:43:11 浏览数 (1)

正则表达式

参考:

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

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

String

  1. replace

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

代码语言:javascript复制
'abcabc'.replace(/a/,'A')
'abcabc'.replace(/a/g,'A')
'abcabc'.replace(/a/gi,'S')
  1. search

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

代码语言:javascript复制
console.log('hello world!'.search(/l/g))
  1. split

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

代码语言:javascript复制
let str = 'a|b|c'
console.log(str.split('|'))
let str2 = 'a|b c**d'
let arr = str2.split(/||s |**/)
console.log(arr)
  1. match

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

代码语言:javascript复制
var str = "hello javascript!"
var reg1 = /a/
console.log(str.match(reg1))
var reg2 = /a/g
console.log(str.match(reg2))

// 小括号问题
var str2 = 'abcabc'
var reg3 = /(b)c/
console.log(str2.match(reg3))
var reg4 = /(b)c/g
console.log(str2.match(reg4))

RegExp

  1. test

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

代码语言:javascript复制
var reg = /abc/
var str = 'abc'
console.log(reg.test(str))
  1. exec

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

代码语言:javascript复制
var reg = /abc/g
var str = 'abcdefgabcefg'
var arr = reg.exec(str)

while(arr){
  console.log(arr)
  arr = reg.exec(str)
}
  1. compile

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

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

代码语言:javascript复制
var reg=/[abc]/gi;
console.log(reg.test('a'));
reg=/[cde]/gi;
console.log(reg.test('a'));
reg.compile(reg);
console.log(reg.test('a'));

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

正则工具

  • 在线工具 regular expressions regulex
  • 图表工具 regexper
  • window 环境

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,并捕获文本到自动命名的组里

(?<name>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 <aa aa> yy 这样的字符串里,最长的配对的尖括号内的内容捕获出来?

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

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

0 人点赞