After testing things out for a different question, I found something unexpected about the way regex_replace works in the Field Calculator, compared to PostgreSQL. The suggested insert ends up duplicated in the output.
The string: 'a_a_a_a_a'.
The desired output: 'a_a_a_a_ca'
I'm testing with two patterns. The first finds all the non-underscore characters at the end of a string, while the second finds the first non-underscore character after the fourth underscore. The patterns:
([^_]*)$
(?<=[^_]_[^_]_[^_]_[^_]_)([^_]{1})
PostgreSQL regex_replace behaviour works as I would expect:
select string,
regexp_replace(string,'([^_]*)$','c\1') as repl_1,
regexp_replace(string,'(?<=[^_]_[^_]_[^_]_[^_]_)([^_]){1}','c\1') as repl_2
from (select 'a_a_a_a_a' as string) pattern
Outcome:
string | repl_1 | repl_2 |
---|---|---|
a_a_a_a_a | a_a_a_a_ca | a_a_a_a_ca |
Field Calculator behaves differently, using the same pattern:
regexp_replace('a_a_a_a_a','([^_]*)$','c')
, as shown by the Output preview, gives 'a_a_a_a_cc'
. Interestingly, the capture group doesn't even have to be called with \1
to get that output.
When I do call the capture group, I again end up getting an unexpected result:
regexp_replace('a_a_a_a_a','([^_]*)$','c\\1') returns 'a_a_a_a_cac'
Using the positive lookbehind in the Field Calculator works fine, however:
regexp_replace('a_a_a_a_a','(?<=[^_]_[^_]_[^_]_[^_]_)([^_]{1})','c\\1')
Returning 'a_a_a_a_ca'
as expected.
Is this just a weird bug with regex_replace in the Field Calculator, or am I missing something obvious?