问号的作用
可选项
问号使正则表达式中的前一个标记为可选。colou?r
可以匹配colour和color 。我们称?
为量词。
通过使用括号将它们组合在一起,然后将问号放在右括号的后面,可以使多个标记成为可选标记。例如:Nov(ember)?
匹配可以匹配Nov和November。
我们可以通过包含多个问号来编写有许多选择方案的正则表达式。Feb(ruary)?23(rd )?
可以匹配February 23rd,February 23,Feb 23rd和Feb 23。
我们也可以使用花括号将某些内容设置为可选。colou{0,1}r
与colou?r
。POSIX BRE和GNU BRE不支持这两种语法。它们要求在花括号前使用反斜杠,这样花括号才有特殊的含义:colou\{0,1\}r
。
正则表达式的重要概念:贪婪
问号?
是从开始到现在引入的第一个贪婪的元字符。问号为正则表达式引擎提供了两种选择:尝试匹配问号所适用的部分,或者不尝试匹配。引擎始终尝试匹配该部分。仅当这导致整个正则表达式失败时,引擎才会尝试忽略问号?
适用的部分。
如果我们将正则表达式Feb 23(rd)?
应用到字符串Tommorow is Feb 23rd,2021
,始终是匹配Feb 23rd,而不是Feb 23。这是因为?
是贪婪的,但是有趣的事情是,虽然问号?
是贪婪的,但是问号?
也有关闭贪婪的功能。我们可以通过在第一个问号之后放置第二个问号来使问号变得懒惰(即关闭贪婪性)。
正则表达式引擎内核
让我们将正则表达式colou?r
应用于字符串I know that colonel likes the color green。
正则表达式中的第一个标记是c 。它成功匹配的第一个位置是在colonel 中的c。引擎继续前进,发现o
匹配o ,l
匹配l ,另一个o
匹配o 。然后引擎检查u
是否匹配n 。这失败了。但是,问号?
告诉正则表达式引擎不匹配u也是可以接受的。因此,引擎向前跳到下一个正则表达式token:r
。但这也无法匹配n 。现在,引擎只能得出结论,整个正则表达式不能在colonel的第一个字符c处匹配。因此,引擎再次尝试将c与colonel的第一个o匹配。
一系列的失败后,c
在color的开始处匹配到字符c,然后是o,l和o匹配以下字符。现在,引擎检查u是否匹配r 。这失败了。问号允许引擎以r继续。这与r匹配,最终引擎报告正则表达式成功匹配了我们字符串中的color。