2010-04-29 101 views
10

您可以在逆序引用中使用反向引用嗎?逆向引用的反向引用

比方說,我想要split無論身後的任何角色重複兩次。

String REGEX1 = "(?<=(.)\\1)"; // DOESN'T WORK! 
    String REGEX2 = "(?<=(?=(.)\\1)..)"; // WORKS! 

    System.out.println(java.util.Arrays.toString(
     "Bazooka killed the poor aardvark (yummy!)" 
     .split(REGEX2) 
    )); // prints "[Bazoo, ka kill, ed the poo, r aa, rdvark (yumm, y!)]" 

使用REGEX2(其中反向引用是嵌套在回顧後內先行)的作品,但REGEX1給在運行時出現此錯誤:

Look-behind group does not have an obvious maximum length near index 8 
(?<=(.)\1) 
     ^

排序是有意義的,我假設,因爲在一般的反向引用可以捕獲任何長度的字符串(如果正則表達式編譯器是有點聰明,雖然,它可確定\1是在這種情況下(.),因此具有有限的長度)。

那麼有沒有一種方法可以在lookbehind中使用反向引用?

如果沒有,您是否總是可以使用這種嵌套的預覽工作?還有其他常用技術嗎?

+1

有趣的是,和+1爲您巧妙的解決方法。我不使用Java,所以我不能自己嘗試 - 如果反向引用的組不在lookaround之後,會發生什麼情況,比如'(?<= \\ 1)(。)'? – 2010-04-29 07:29:09

+0

@Tim:它導致基本相同的'PatternSyntaxException'。 http://codingbat.com/prob/p266235 – polygenelubricants 2010-04-29 07:45:19

+0

@polygenelubricants我希望我能給予好評這個表達式:順便說一句,如果有人想玩弄這個問題的一個變種,我只是codingBat着一個?(<= (?=(。)\\ 1)..)至少10次。十分優雅! – Eugene 2012-08-14 08:35:49

回答

5

看起來你的懷疑是正確的,反向引用通常不能在Java lookbehinds中使用。您提出的解決方法使得lookbehind的有限長度更加明確,並且對我來說看起來非常聰明。

我很好奇找出Python做這個正則表達式。 Python只支持固定長度的lookbehind,不像Java那樣有限長,但是這個正則表達式是固定長度的。我不能直接使用re.split()因爲Python的re.split()在一個空的比賽從來沒有分裂,但我想我發現了一個bug在re.sub()

>>> r=re.compile("(?<=(.)\\1)") 
>>> a=re.sub(r,"|", "Bazooka killed the poor aardvark (yummy!)") 
>>> a 
'Bazo|oka kil|led the po|or a|ardvark (yum|my!)' 

的回顧後匹配兩個重複的字符之間!

+0

查看http://stackoverflow.com/questions/2628534/codingbat-plusout-using-regex更多正則表達式的樂趣。 – polygenelubricants 2010-04-29 08:32:32

+0

雖然're.split()'不會在空匹配上分裂,這很愚蠢。爲什麼他們會這樣做?我認爲有很多時候你想簡單地基於斷言來分割,而不是實際的非空分隔符。 – polygenelubricants 2010-04-29 08:37:13

+0

我對Python bugtracker提出了同樣的問題。這可能是意想不到的,但被遺留下來不會導致兼容性問題;有一個主要的正則表達式引擎正在進行修改,但可能需要一段時間,直到新的正則表達式模塊被合併到標準庫中。 – 2010-04-29 08:56:28