2016-11-10 3 views
0

私はちょうどregexp_replace PostgreSQLの機能が不思議な振る舞いを見つけました。それはバグのように見えますが、私はいつも自分自身をまず疑う。私は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\%2\_3」の「1\12\13」を生成します。誰かが私に何が間違っているのかを教えてもらえれば分かります。文字列の特定の文字の前にバックスラッシュを追加するだけです。

UPDATE:私は私の元の例は、まだ少し非論理的かつ一貫性のないと思われる

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

を実行することにより、目的の動作を実現することができました。同じE'...'シンタックス4のバックスラッシュを使用すると、異なる結果が生じる可能性があります。

答えて

1

2番目のクエリでは、バックスラッシュエスケープ文字列が文字列レベルで処理された後、置換文字列\\1があります。

エスケープされたバックスラッシュは、\1がバックリファレンスとして認識されないようにします。リテラルのバックスラッシュとバックリファレンスを取得するには、置換文字列が\\\1になるように、別のバックスラッシュのセットが必要です。すべてのリテラルバックスラッシュをエスケープする必要があるので、それらのすべてを二重にする必要があります。

+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'にしてください。


そして簡単な使用を交換するだけでちょうど2つの文字のために:

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

正規表現は強力ですが、価格のために。いくつかネストされた単純なreplace()コールでさえ、単一のregexp_replace()より安いです。

+0

前に置き換えて正規表現対この考えを持っていましたが、それほど重要ではありませんでした。ありがとう! –

関連する問題