我最近一直在研究正则表达式,并发现该?
运算符使*
, +
, 或?
惰性。我的问题是它是如何做到的?*?
例如是一个特殊的运算符,还是对?
有影响*
?换句话说,正则表达式*?
本身是否识别为一个运算符,或者正则表达式是否识别*?
为两个单独的运算符*
和?
?如果*?
是被识别为两个独立的运营商的情况,这对使其变得懒惰有什么?
影响。*
如果?
意味着 the*
是可选的,这不应该意味着*
根本不需要存在。如果是这样,那么在声明中.*?
正则表达式不会只匹配单独的字母和整个字符串而不是较短的字符串吗?请解释一下,我很想了解。非常感谢。
4 回答
?
在不同的上下文中可能意味着很多不同的事情。
- 在一个普通的正则表达式标记(一个字符、一个速记、一个字符类、一个组......)之后,它的意思是“匹配上一个项目 0-1 次”。
- 在像
?
,*
,+
,之类的量词之后{n,m}
,它具有不同的含义:“使先前的量词变得懒惰而不是贪婪(如果这是默认值;但是可以更改 - 例如在 PHP 中,/U
修饰符默认情况下使所有量词变得懒惰) ,所以额外的?
让他们变得贪婪)。 在左括号之后,它标志着一个特殊结构的开始,例如
a)
(?s)
:模式修饰符(“打开dotall模式”)
b)(?:...)
:使组不捕获
c)(?=...)
或(?!...)
:前瞻断言
d)(?<=...)
或(?<!...)
:后向断言
e)(?>...)
:原子组
f)(?<foo>...)
:命名捕获组
g)(?#comment)
:内联注释, 被正则表达式引擎忽略
h)(?(?=if)then|else)
: 条件
和别的。并非所有结构都适用于所有正则表达式。
- 在字符类 (
[?]
) 中,它只是逐字匹配?
。
我认为一点历史会更容易理解。当 Larry Wall 想要发展正则表达式语法以支持新功能时,他的选择受到了严重限制。他不能仅仅命令(例如)%
现在是支持新功能“XYZ”的元字符。这将打破数以百万计的现有正则表达式,这些正则表达式恰好用于%
匹配文字百分号。
他能做的是获取一个已经定义的元字符,并以使其原始功能没有意义的方式使用它。例如,任何连续包含两个量词的正则表达式都是无效的,因此可以安全地说一个?
又一个量词现在将它变成一个不情愿的量词(比“懒惰”IMO 更好的名称;非贪婪也很好) . 所以你的问题的答案是?
不修改,*
是 *?
一个单一的实体:一个不情愿的量词。+
所有格量词 (*+
等{0,2}+
)也是如此。
组语法也发生了类似的过程。在未转义的左括号之后有一个量词是没有意义的,所以可以肯定地说(?
now 标志着一个特殊组构造的开始。但仅问号就只能支持一个新特性,所以后面要跟的?
本身必须至少再跟一个字符来表示它是哪一种组((?:...)
,(?<!...)
等)。同样,(?:
是单个实体:非捕获组的开始分隔符。
我不知道他为什么两次都使用问号。我确实知道Perl 6 规则(Perl 5 正则表达式的自下而上重写)已经消除了所有这些废话并使用了无限更明智的语法。
假设您有以下文本:
BAAAAAAAAD
以下正则表达式将返回:
/B(A+)/ => 'BAAAAAAAA'
/B(A+?)/ => 'BA'
/B(A*)/ => 'BAAAAAAAA'
/B(A*?)/ => 'B'
增加“?” + 和 * 运算符使它们“惰性” - 即它们将匹配表达式为真所需的绝对最小值。而默认情况下 * 和 + 运算符是“贪婪的”,并尝试尽可能匹配表达式为真。
请记住 + 表示“一个或多个”,因此最小值将是“如果可能,则为一个,如果绝对必要则更多”,而最大值将是“如果可能,则为一个,如果绝对必要则为一个”。
并且 * 表示“零或更多”,因此最小值将是“如果可能则没有,如果绝对必要则更多”,而最大值将是“如果可能则全部,如果绝对必要则为零”。
我猜这在很大程度上取决于实现。但是由于我知道的每个量词都可以修改,?
因此以这种方式实现它可能是合理的。