什么是Java正则表达式中的占有量词用于?

时间:2014-09-24 00:22:41

标签: java regex

我正在阅读Java中的正则表达式。我理解占有量词不会回溯并释放角色,以便让其他群体获得匹配。 但我无法想象在现实中使用占有量词的任何情况。 我已经阅读了一些资源,说由于占有量词不会回溯,它们不需要记住输入字符串中每个字符的位置,这有助于显着提高正则表达式引擎的性能。 我通过编写一个例子对此进行了测试:

我有一个包含大约数千个数字的字符串。

首先我定义了一个贪心:String regex = "(\d+)";

然后我计算了所花费的时间。

第二:我改为占有欲:String regex = "(\d++)";

此外,我计算了所花费的时间,但我没有看到时间上的任何差异

我误解了什么吗?

此外,任何人都可以给我一些使用占有量词的具体案例吗?

关于这个术语:在“Java Regular Expressions Taming the Java.Util.Regex Engine by Mehran Habibi”一书中,他使用了术语“possessive qualifiers”,而在互联网上阅读时,人们使用了“Possessive quantifier”。哪一个是正确的还是两者都是?

2 个答案:

答案 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。因此,它会同时吃AH。第二组只留下0,但第二组不能吃掉那个角色。因此,正则表达式失败,使用非占有量词将导致成功匹配。然而,字符串Aw将成功匹配,因为第一组对w不感兴趣...

答案 1 :(得分:1)

默认情况下,量化是贪婪的。他们会尝试尽可能地匹配。占有量词可以防止回溯,这意味着正则表达式匹配的内容不会被回溯,即使这会导致整个匹配失败。如Regex Tutorial ( Possessive Quantifiers )中所述......

  

占有量词是防止正则表达式引擎的一种方法   尝试所有排列。这主要用于提高性能   原因。您还可以使用占有量词来消除某些   匹配。