2014-03-30 52 views
2

我有這個正則表達式^(?!.*?([aceg]).*?\1)(?!.*?([i])(?:.*?\2){2})[acegi]+$,它的作用是expected(例如在Ruby中),但由於「無效的反向引用號碼」而不在PostgreSQL中。Postgresql:無效的正則表達式:無效的反向引用號碼

如何解決它並保持給定的功能? SQL命令的

部分:WHERE (name ~ '^(?!.*?([aceg]).*?\1)(?!.*?([i])(?:.*?\2){2})[acegi]+$')

注:我試圖逃避反斜線,像\\沒有任何錯誤,但PG正在返回無效的比賽(如 「AAA」)。

回答

3

Postgresql的問題在於,首先,它不支持在其超前斷言中包含捕獲組。這就是說,在先行中的所有捕獲組將作爲非捕獲組((?: ...)),重點煤礦進行處理:

前瞻約束不能包含反向引用(見Section 9.7.3.3),並內的所有這些括號被認爲是不捕獲的。[1]

所以,即使PostgreSQL的做了前瞻內有支持反向引用,它仍然會失敗,由於上述約束按預期方式工作(沒有捕獲組,你不能有一個反向引用)。


可能的解決方法(將是冗長複雜要求不幸)。將計數每個字符的數目:

WHERE 
    LENGTH(REGEXP_REPLACE(name, '[^a]+', '', 'g')) < 2 AND 
    LENGTH(REGEXP_REPLACE(name, '[^c]+', '', 'g')) < 2 AND 
    LENGTH(REGEXP_REPLACE(name, '[^e]+', '', 'g')) < 2 AND 
    LENGTH(REGEXP_REPLACE(name, '[^g]+', '', 'g')) < 2 AND 
    LENGTH(REGEXP_REPLACE(name, '[^i]+', '', 'g')) < 3 AND 
    LENGTH(REGEXP_REPLACE(name, '[acegi]+', '', 'g')) = 0; 

[取條件和改性從this answer;最後一行是確保字符串中只有這些字符]

+0

TY,我想它不能被簡化? '長度(REGEXP_REPLACE(name,'[^ aceg] +','','g'))<2 AND' – Nikos

+0

@Nikos我不這麼認爲。如果說,你有'name ='aaccee'這是有效的,因爲所有的字母出現少於2次,並使用上述,替換將刪除所有除a,c,e和g字母,這意味着它將刪除沒有。長度將返回6(小於2)並且將被「匹配」。 – Jerry

+0

它沒有爲我工作的最後一個條件,所以我用正則表達式替換'^ [acegi] + $'。 – Nikos

1
+0

另一個傑瑞對自己的好事太聰明瞭。 :P –

+2

請鏈接到當前的文檔,而不是一個古老的版本。在這種情況下,這種限制仍然存在,但人們通常從舊文檔開始工作,並基於此做出不好的決定。 –