缩短RegEx

时间:2011-12-09 17:02:06

标签: java regex

在Java RegEx中,我有以下内容:

(1abc\\d{2})|(2abc\\d{3})|(3abc\\d{4})

我想从RegEx中提取'abc \ d'并用以下内容替换RegEx:

(1|2|3)abc\\d({2]|{3}|{4})

问题是1属于{2},2属于{3},3属于{4}。所以一个很好的比赛是1abc12,但是一场糟糕的比赛是1abc123。

我最近学习了RegEx,我觉得我缺少一些关于RegEx的知识来实现​​这一点。它甚至可能吗?

5 个答案:

答案 0 :(得分:1)

使用正则表达式无法描述所描述的内容。通常,表达式的后面部分不能依赖于表达式的早期部分的匹配结果。例如,您不能编写与平衡括号或matching HTML tags匹配的正则表达式。

某些实现提供了扩展,为此提供了异常(不规则表达式),但我认为它们不适用于此。

答案 1 :(得分:1)

您可以通过正则表达式中的\n使用反向引用来引用以前匹配的组,但这些只能再次匹配字符串,它们无法更改模式的规则。

例如(1|2|3)abc\1匹配1abc12abc2但不匹配1abc2,即\1将匹配第一个括号。

理想情况下,我们希望做一些谎言(1|2|3)abc\d{\1 + 1},但Java不支持其正则表达式中的代码或表达式。

所以不幸的是,你想要的是不可能的,或者说你的第一个表达可能就像它会得到的一样好。

答案 2 :(得分:1)

可以用伪条件方式完成,但治愈可能比疾病更糟糕。

我使用这种方式(下面)的唯一方法是,如果'text'(在这种情况下为abc)是非常大的东西,以这种方式将其分解会产生超过包括它的时间收益在现在存在的每次交替中。一些非常大的文本的示例可能是“abc[^\d]+432xyz”,或任何具有开放式量词或导致大量回溯的内容。

这适用于Java ..

"^(?:1()|2()|3())abc(?:(?=\\1)\\d{2}|(?=\\2)\\d{3}|(?=\\3)\\d{4})$"

(扩展)

^       # Begin, all capture buffers are undefined and empty
  (?:
      1()     # If '1' found, set capture buffer 1 to defined (but empty)
    | 2()     # If '2' found, set capture buffer 2 to defined (but empty)
    | 3()     # If '3' found, set capture buffer 3 to defined (but empty)
  )
  abc      # The text factored out
  (?:
       # The below could also be  \1\d{2}|\2\d{3}|\3\d{4} as well

      (?=\1)\d{2}    #     Assertion: is capt buffer 1 defined?, get next two digits
    | (?=\2)\d{3}    # or, Assertion: is capt buffer 2 defined?, get next three digits
    | (?=\3)\d{4}    # or, Assertion: is capt buffer 3 defined?, get next four digits
  )
$      # End

另外,正如有人提到的那样,你可以进行一般性捕获,然后对结果进行后处理以确定它是否有效。

像这样:^(1|2|3)abc(\d{2,4})$。然后在捕获缓冲区1上进行切换,然后在捕获缓冲区2的长度上进行切换。

答案 3 :(得分:0)

由于数字1,2,3分别与你的正则表达式组{2},{3}和{4}有关,我认为没有办法可以取代公共子表达式。

答案 4 :(得分:0)

不是一个完美的解决方案,但您可以使用字符串函数来提取第一个数字(如果格式不能保证是合适的模式,则使用正则表达式)。然后使用第一个数字,添加一个,并在一个非常简单的正则表达式中使用它。