正则表达式小结

avatar
前端开发工程师 @豌豆公主

正则表达式

  • 定义一个正则表达式


const regexp = new RegExp('pattern', 'flags');


const regexp = /pattern/; // 没有修饰符

const regexp = /pattern/gmi; // 有修饰符

接下来通过一个例子回忆一下正则表达式:

<[a-zA-Z]+.?>([\s\S]?)</[a-zA-Z]*?>

几道练习题

  • 什么字符串可以匹配/^$/
  • 对于正则表达式/Java[^script]/,字符串Java和JavaScript会匹配吗?
  • /abc.com/.test('abccom');
  • 贪婪模式、非贪婪模式

贪婪和非贪婪模式是对于量词(+、*、?)而言的;贪婪模式下,量词都会尽可能多的重复,而非贪婪模式恰恰相反,重复最少的次数。他们的区别就是在量词后加?

举个🌰:


const regexp = /".+"/g;

const str = 'hello "java", hello "javascript"';

str.match(regexp); //

  • 捕获组

使用()将一部分模式括起来

使用捕获组对正则表达式有两个影响:

(1)允许将匹配的一部分作为结果数组中的单独项;

(2)可以将括号视为一个整体;

举个🌰:


const regexp = /(abc)+/;

'abcabcabc def'.match(regexp);

可选组

即使可选组中的匹配项不存在,但是在匹配结果中也有相应的数组项,并且等于undefined

举个🌰:


const regexp = /a(b)?(c)?/;

const result = 'a'.match(regexp);

console.log(result);

命名组

对于上面的匹配结果数组,如果要获取某一项的值,则需要知道对应数组的下标,如果捕获组比较多,则不容易记住;此时可以使用命名组,给捕获组起一个别名:?

举个🌰:


const regexp = /(?<year>[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;

const str = "2022-10-31";

const groups = str.match(regexp).groups;

console.log(groups)

非捕获组(?:)

有时我们想对几个规则同时使用量词,这时需要用到捕获组,但是又不想让捕获组匹配的内容出现在结果中,这时就可以用非捕获组实现

举个🌰:


const regexp = /(?:[0-9]{4})-(?<month>[0-9]{2})-(?<day>[0-9]{2})/;

const str = "2022-10-31";

const groups = str.match(regexp).groups;

console.log(groups)

  • 反向引用

先看一个🌰:


const regexp = /<h[1-6]>.*<\/h[1-6]>/; // 识别h1—6标签

const result = regexp.test('<h1>xxx</h2>');

console.log(result); // true

如果能够在后面获取到捕获组中的内容就好了,庆幸的是,正则表达式中是支持的,就是通过反向引用:

我们不仅可以在结果或替换字符串中使用捕获组 (...) 的内容,还可以在模式本身中使用它们。

按编号反向引用 \n

这种方式是使用捕获组的编号进行反向引用:


const regexp = /<h([1-6])>.*<\/h\1>/; // 识别h1—6标签

const result = regexp.test('<h1>xxx</h2>');

console.log(result); // false

按命名反向引用 \k


const regexp = /<h(?<tag>[1-6])>.*<\/h\k<tag>>/; // 识别h1—6标签

const result = regexp.test('<h1>xxx</h2>');

console.log(result); // true

  • 前瞻和后瞻

有时我们只需要为一个模式找到那些在另一个模式之后或之前的匹配项。 有一种特殊的语法,称为“前瞻断言(lookahead)”和“后瞻断言(lookbehind)”。

有四种形式:

1、(?=pattern) 零宽正向先行断言(zero-width positive lookahead assertion)

x(?=y),它表示“仅在后面是 Y 时匹配 X”

2、(?!pattern) 零宽负向先行断言(zero-width negative lookahead assertion)

x(?!y),它表示“仅在后面不是 Y 时匹配 X”

3、(?<=pattern) 零宽正向后行断言(zero-width positive lookbehind assertion)

(?<=y)x,它表示“仅在前面是 Y 时匹配 X”

4、(?<!pattern) 零宽负向后行断言(zero-width negative lookbehind assertion)

(?<!y)x,它表示“仅在前面不是 Y 时匹配 X”

这里”零宽“的解释:他们只匹配位置,不占用字符

🌰🌰🌰


const regexp = /o(?=\s)/;

const str = 'hello world';

console.log(str.match(regexp));