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

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

1.普通的问号符号

因为 ? 是特殊符号,所以如果想把 ? 当做正常的问号匹配,就需要加转义 \?

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

2.量词

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

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

3.惰性模式匹配

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

模式 说明
连续出现 n 到 m 次。贪婪模式
至少连续出现 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 不会保存该分组的数据,如下所示

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

5.断言

1.正先行断言(前瞻)

(?=X)

2.负先行断言(前瞻)

(?!X)

3.正后发断言(后顾)

(?<=X)

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) 同理

posted @ 2021-08-25 10:24  进军的蜗牛  阅读(5108)  评论(0编辑  收藏  举报