我偶然发现了regexp_replace
PostgreSQL函数的奇怪行为。它看起来像一个bug但我总是怀疑自己。我跑的时候
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'...'
语法4反斜杠可能会产生不同的结果。
答案 0 :(得分:1)
在第二个查询中,在字符串级别处理反斜杠转义后,您将拥有替换字符串\\1
。
发生的事情是,转义的反斜杠会阻止\1
被识别为反向引用。您需要另一组反斜杠,以便替换字符串\\\1
以获取文字反斜杠和反向引用。由于每个字面反斜杠都需要进行转义,因此需要将它们全部加倍。
SELECT regexp_replace(E'1%2_3', '([_%])', E'\\\\\\1', 'g')
答案 1 :(得分:1)
我不会首先在Postgres中使用过时的Posix转义语法。您使用standard_conforming_strings = off
运行过期版本吗?因为如果不是,请简化:
SELECT regexp_replace('1%2_3', '([_%])', '\\\1', 'g')
您只需添加一个\
即可逃避正则表达式模式中\
的特殊含义。
必须处理前缀为E
的字符串,这需要额外的费用,并且始终存在使用特殊字符的意外副作用的风险。为{<1}}写一个你想要提供的字符串是没有意义的。在任何情况下都只需E'1%2_3'
。
仅用两个字符代替简单使用:
'1%2_3'
正则表达式很强大,但需要付出代价。即使是几个嵌套的简单SELECT replace(replace('1%2_3', '_', '\_'), '%', '\%')
调用也比单个replace()
便宜。