我正在阅读Java中的正则表达式。我理解占有量词不会回溯并释放角色,以便让其他群体获得匹配。 但我无法想象在现实中使用占有量词的任何情况。 我已经阅读了一些资源,说由于占有量词不会回溯,它们不需要记住输入字符串中每个字符的位置,这有助于显着提高正则表达式引擎的性能。 我通过编写一个例子对此进行了测试:
我有一个包含大约数千个数字的字符串。
首先我定义了一个贪心:String regex = "(\d+)";
然后我计算了所花费的时间。
第二:我改为占有欲:String regex = "(\d++)";
此外,我计算了所花费的时间,但我没有看到时间上的任何差异
我误解了什么吗?
此外,任何人都可以给我一些使用占有量词的具体案例吗?
关于这个术语:在“Java Regular Expressions Taming the Java.Util.Regex Engine by Mehran Habibi
”一书中,他使用了术语“possessive qualifiers
”,而在互联网上阅读时,人们使用了“Possessive quantifier
”。哪一个是正确的还是两者都是?
答案 0 :(得分:2)
占有量词是贪婪的量词(他们试图匹配尽可能多的字符)并且不回溯(如果占有量词远远地去,匹配就会失败)。
示例强>
正常(贪婪)量词
假设你有以下正则表达式:
^([A-Za-z0-9]+)([A-Z0-9][A-Z0-9])(.*)
正则表达式旨在匹配“一个或多个字母数字字符(不区分大小写)
[A-Za-z0-9]
,并且应该以两个字母数字字符结尾,然后可以出现任何字符。
遵守此约束的任何字符串都将匹配。 AAA
也是如此。可以声称第二个和第三个A
应属于第二个组,但这会导致字符串不匹配。因此,正则表达式具有智能(使用动态编程),以知道何时离开(第一)船。
非贪婪量词
现在可能出现的问题是第一组对于数据提取而言“过于贪婪”。假设您有以下字符串AAAAAAA
。可能有几个细分:(A)(AA)(AAAA)
,(AA)(AA)(AAA)
等。默认情况下,正则表达式中的每个组都尽可能贪婪(只要这对字符串是否仍然匹配这一事实没有影响)。因此,正则表达式将细分(AAAAA)(AA)()
中的字符串。如果您想以这样的方式提取数据,那么从一个字符传递的那一刻开始,从[A-Z0-9]
范围内的两个字符出现的那一刻起,正则表达式应该移动到下一个组。
为了达到这个目的,你可以写:
^([A-Za-z0-9]+?)([A-Z0-9][A-Z0-9])(.*)
字符串AAAAAAA
将与(A)(AA)(AAAA)
匹配。
占有量词
占有量词是贪婪的量词,但一旦有可能,他们永远不会将角色带回另一个群体。例如:
^([A-Z]++)([H-Zw])(.*)
如果您要写^([A-Z]+)([H-Z])(.*)
,则匹配字符串AH0
。第一组是贪婪的(取A
),但由于吃(有时使用这个词)H
会导致字符串不匹配,所以它愿意放弃H
。使用占有量词。该组织也不愿意放弃H
。因此,它会同时吃A
和H
。第二组只留下0
,但第二组不能吃掉那个角色。因此,正则表达式失败,使用非占有量词将导致成功匹配。然而,字符串Aw
将成功匹配,因为第一组对w
不感兴趣...
答案 1 :(得分:1)
默认情况下,量化是贪婪的。他们会尝试尽可能地匹配。占有量词可以防止回溯,这意味着正则表达式匹配的内容不会被回溯,即使这会导致整个匹配失败。如Regex Tutorial ( Possessive Quantifiers )中所述......
占有量词是防止正则表达式引擎的一种方法 尝试所有排列。这主要用于提高性能 原因。您还可以使用占有量词来消除某些 匹配。