2016-11-10 108 views
0

我只是偶然發現了PostgreSQL函數的一個好奇的行爲regexp_replace。它看起來像一個錯誤,但我總是首先懷疑自己。當我運行在regexp_replace中看似不正確的正則表達式評估

SELECT regexp_replace(E'1%2_3', '([_%])', E'\\ \\1', 'g') 

它正確的前綴或者與反斜槓+空格下劃線或百分比,併產生「1\ %2\ _3」。然而,當我除去空間(它不必是空間,可以是任何字符)

SELECT regexp_replace(E'1%2_3', '([_%])', E'\\\\1', 'g') 

它停止使用,以代替所捕獲括號表達式,併產生「1\12\13」而不是「1\%2\_3」。如果有人能告訴我我做錯了什麼,我將不勝感激。我只需要在字符串中的某些字符之前添加反斜槓。

更新:我可以通過運行

SELECT regexp_replace(E'1%2_3', '([_%])', E'\\\\\\1', 'g') 

我原來的例子,以達到預期的行爲仍似乎有點不合邏輯,不符。不一致之處在於使用相同的E'...'語法反斜槓可能會產生不同的結果。

回答

1

在第二個查詢中,在字符串級別處理反斜槓escapES之後,您將擁有替換字符串\\1

發生了什麼是轉義反斜槓防止\1被識別爲反向引用。您需要另一組反斜槓,以便替換字符串爲\\\1以獲得文字反斜槓和反向引用。由於每個字面反斜槓都需要被轉義,所以你需要把所有的反斜槓加倍。

SELECT regexp_replace(E'1%2_3', '([_%])', E'\\\\\\1', 'g') 
+0

謝謝Barmar我剛剛在幾次實驗後發現了這個問題 –

1

我不會在第一時間在Postgres中使用過時的Posix轉義語法。您是否在運行standard_conforming_strings = off的過期版本?因爲如果你不是,簡化:

SELECT regexp_replace('1%2_3', '([_%])', '\\\1', 'g') 

你只需要添加一個\逃脫\在正規表達式的特殊含義。

絃樂與E前綴必須處理,花費一點點額外的和總有意想不到的副作用特殊字符的風險。對於要提供的字符串而言,編寫E'1%2_3'毫無意義,也是如此。無論如何,只要做到這一點'1%2_3'


而對於纔剛剛兩個字符來代替簡單的使用:

SELECT replace(replace('1%2_3', '_', '\_'), '%', '\%') 

正則表達式是強大的,但對於一個價格。甚至幾個嵌套的簡單replace()調用比單個regexp_replace()便宜。

+0

我曾經想過關於正則表達式vs之前的替換,但沒有給它太多的意義。謝謝! –

相關問題