正则表达式里问号?的用法

2021年11月24日 阅读数:2
这篇文章主要向大家介绍正则表达式里问号?的用法,主要内容包括基础应用、实用技巧、原理机制等方面,希望对大家有所帮助。

文章原文:https://www.cnblogs.com/yalong/p/15183458.htmlhtml

1.普通的问号符号

由于 ? 是特殊符号,因此若是想把 ? 当作正常的问号匹配,就须要加转义 \?code

示例
var regex = /123\?456/
var str = '123?456'
regex.test(str)  // true

2.量词

问号能够表示重复前面内容的0次或一次,也就是要么不出现,要么出现一次htm

示例
var regex = /1?23/
regex.test('123') // true
regex.test('1123') // true
regex.test('1234') // true
regex.test('121') // false

3.惰性模式匹配

量词模式是贪婪模式,在量词后面加上问号,就变成了惰性匹配
看以下量词的表格blog

模式 说明
{n,m} 连续出现 n 到 m 次。贪婪模式
{n,} 至少连续出现 n 次。贪婪模式
{n} 连续出现 n 次。贪婪模式
? 等价于 {0,1}。贪婪模式
+ 等价于 {1,}。贪婪模式
* 等价于 {0,}。贪婪模式

量词后面加上问号后以下内存

模式 说明
{n,m}? 连续出现 n 到 m 次。惰性模式
{n,}? 至少连续出现 n 次。惰性模式
{n}? 连续出现 n 次。惰性模式
?? 等价于 {0,1}?。惰性模式
+? 等价于 {1,}?。惰性模式
*? 等价于 {0,}?。惰性模式
贪婪模式 跟 惰性模式的区别
  1. 贪婪匹配是先看整个字符串是否匹配,若是不匹配,它会去掉字符串的最后一个字符,并再次尝试,若是还不匹配,那么再去掉当前最后一个,直到发现匹配或不剩任何字符。
  2. 惰性匹配是从左侧第一个字符开始向右匹配, 先看第一个字符是否是一个匹配, 若是不匹配就加入下一个字符再尝式匹配, 直到发现匹配

4.非捕获性分组

  1. 正常只使用括号就是捕获模式,能够捕获括号里的数据,保存在内存中,因此捕获模式会占用更多内存
  2. 非捕获模式,就是在里面的最前面加?:
示例

RegExp 会保存分组里的数据, 以下所示字符串

var regex = /(\d{4})-(\d{2})-(\d{2})/
regex.test('2011-11-12') // true
RegExp.$1 // "2011"
RegExp.$2 // "11"
RegExp.$3 // "12"

使用?:的分组就是非捕获模式,RegExp 不会保存该分组的数据,以下所示get

var regex = /(?:\d{4})-(\d{2})-(?:\d{2})/
regex.test('2011-11-12') // true
RegExp.$1 // "11"
RegExp.$2 // ""

5.断言

1.正先行断言(前瞻)

(?=X)console

2.负先行断言(前瞻)

(?!X)table

3.正后发断言(后顾)

(?<=X)test

4.负后发断言(后顾)

(?<!X)

语法 说明
(?=X ) 正先行断言。仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。例如,/w+(?=/d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯
(?!X) 负先行断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,例如,/w+(?!/d) 与后不跟数字的单词匹配,而不与该数字匹配
(?<=X) 正后发断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。此构造不会回溯
(?<!X) 负后发断言。仅当子表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?<!19)99 与不跟在 19 后面的 99 的实例匹配
简单来讲,前瞻就是 看后面等于(?=), 后面不等于 (?!), 后顾就是 前面等于 (?<=), 前面不等于 (?<!)

好比 (?<!AA)eat(?=milk) 表示, eat 前面不能是AA, 后面必须是 milk

好比 (?<=AA)eat(?!milk) 表示 eat 前面必须是AA, 后面不能是milk

示例
  let str1 = "VVeatmilk"
  let str2 = "AAeatfood"
  let patt1 = new RegExp("(?<!AA)eat(?=milk)");
  let patt2 = new RegExp("(?<=AA)eat(?!milk)");
  let result1 = patt1.test(str1);
  let result2 = patt2.test(str2);
  console.log(result1) // true
  console.log(result2) // true
以(?=p) 和 (?!p)为例

(?=p),其中 p 是一个子模式,即 p 前面的位置,或者说,该位置后面的字符要匹配 p
好比 (?=l),表示 l 字符前面的位置,例如:

var result = "hello".replace(/(?=l)/g, '#');
console.log(result);
// => "he#l#lo"

而 (?!p) 就是 (?=p) 的反面意思,好比:

 var result = "hello".replace(/(?!l)/g, '#');
 console.log(result);
 // => "#h#ell#o#"

(?<=p)(?<!p) 同理