OK, našel jsem odpověď. Zřejmě potřebuji dvojité escapování zpětného lomítka v nahrazení. Také potřebuji E
-předpona a dvojitá zpětná lomítka ve vyhledávacím vzoru na starších verzích postgresu (v mém případě 8.3). Konečný kód vypadá takto:
regexp_replace('abc [def]', E'([\\[\\]\\(\\)\\\\\?\\|_%])', E'\\\\\\1', 'g')
Ano, vypadá to hrozně, ale funguje to :)