
正则表达式中的问号(?)
在正则表达式中,问号(?)是一个具有多重含义的特殊字符。它的具体意义取决于它所处的上下文环境。以下是问号在不同场景下的几种主要用途:
零次或一次匹配
- 当问号紧跟在一个字符、一个字符类(用方括号表示)、或者一个子表达式后面时,它表示前面的元素可以出现零次或一次。这相当于 {0,1} 的量词效果。colou?r // 可以匹配 "color" 或 "colour" [a-z]? // 匹配零个或一个小写字母 (abc)? // 匹配零个或一个 "abc" 子串
非贪婪匹配
- 在量词(如 *, +, {})后面加上问号,可以使该量词变为非贪婪模式(也称为懒惰模式),即尽可能少地匹配字符。.*? // 非贪婪地匹配任意数量的字符(尽可能少的匹配) a+? // 非贪婪地匹配一个或多个 'a'(尽可能少的匹配) a{1,3}? // 非贪婪地匹配一到三个 'a'(尽可能少的匹配)
前瞻和后顾断言
- 问号还可以用于构建前瞻(lookahead)和后顾(lookbehind)断言,这些断言用于检查某个条件是否满足,但不消耗输入字符串的字符。
- 正向前瞻 (?=...):如果后面的字符序列符合某个模式,则匹配成功。foo(?=bar) // 如果 "foo" 后面紧跟着 "bar",则匹配 "foo"(但 "bar" 不被包含在匹配结果中)
- 负向前瞻 (?!...):如果后面的字符序列不符合某个模式,则匹配成功。foo(?!bar) // 如果 "foo" 后面不是 "bar",则匹配 "foo"
- 正向后顾 (?<=...) 和 负向后顾 (?<!...) 也存在,但它们在某些正则引擎中可能不被支持。(?<=\d+)abc // 如果 "abc" 前面是数字,则匹配 "abc"(数字部分不被包含在匹配结果中) (?<!\d+)abc // 如果 "abc" 前面不是数字,则匹配 "abc"
- 问号还可以用于构建前瞻(lookahead)和后顾(lookbehind)断言,这些断言用于检查某个条件是否满足,但不消耗输入字符串的字符。
分组捕获的非捕获版本
- 使用 (?:...) 语法创建一个不捕获的分组,有时为了与分组语法 (...) 区别开来,理解其逻辑作用时会用到问号作为对比说明,虽然问号本身并不直接参与这一功能。不过,值得注意的是,这种用法中问号并不直接作用于分组的定义,而是解释时使用的一个辅助说明点。(?:abc) // 一个不会捕获匹配的分组,只用于分组逻辑而不存储匹配内容
了解问号在这些不同情况下的用法,可以帮助你更灵活地编写和理解正则表达式。
