(正規表現, PHP, JavaScript) MySQLの改行文字(\n)を、SQLite用に置換したい

たとえば、下記のようなMySQL用のSQLがあるとします。


(MySQL)
INSERT INTO tbl VALUES('aaa\naaa', 'bbb\n\nbbb', 'ccc\\nccc', '\\\nddd\nddd');
(\n)は、PHPなどでデータを取得した際、改行として扱われます。
しかし、これをそのままSQLiteで使うことはできません。
SQLiteでは、改行文字ではなく、改行そのものを使わなければなりません。

(SQLite)
INSERT INTO tbl VALUES('aaa
aaa', 'bbb

bbb', 'ccc\
ccc', '\\
ddd
ddd');

というわけで、改行文字を改行そのものに置換する処理を、PHPJavaScript両方で作成します。


正規表現は、以前の記事で紹介した方法を流用します。
『奇数回の連続バックスラッシュ + n』ならば、改行文字。
『偶数回の連続バックスラッシュ + n』ならば、単なる"n"。
という判断方法です。
http://d.hatena.ne.jp/sutara_lumpur/20120720/1342760656


では、PHPの実例です。


(PHP)
$line = 'INSERT INTO tbl VALUES(\'aaa\\naaa\', \'bbb\\n\\nbbb\', \'ccc\\\\nccc\', \'\\\\\\nddd\\nddd\');';
$line = preg_replace('/((?:(?!\\\\).)?(?:\\\\\\\\)*)(\\\\n)/us', '\1'."\n", $line);
echo $line;
コールバック関数へ送って処理する"preg_replace_callback"ではなく、一般的な"preg_replace"で十分です。
'\1'は後方参照です。
この場合は、(\n)の前の連続バックスラッシュと、その前のバックスラッシュ以外の文字が格納されます。


次のJavaScriptで悩みました (-_-;)
まずは、実例を見てください。


(JavaScript)
var str = 'INSERT INTO tbl VALUES(\'aaa\\naaa\', \'bbb\\n\\nbbb\', \'ccc\\\\nccc\', \'\\\\\\nddd\\nddd\');';
str = str.replace(
/((?:(?!\\).)?(?:\\\\)*)(\\n)/gm,
function() {
return arguments[1] + '\n';
}
);
alert(str);
『arguments[1] + '\n'』を返すためだけに、わざわざコールバック関数を使っています。
PHPと同じく、後方参照を使ってすっきり記述できるのでは?と思うでしょう。
でも、ダメなんです…。

(! 正常に置換されない)
str = str.replace(/((?:(?!\\).)?(?:\\\\)*)(\\n)/gm, '\1\n');
今作っている処理ではJavaScriptは使わないのに、ブログ記事用にPHPだけでなくJavaScriptでもサンプルコードを作ろうと思ったら意外な泥沼にハマッてしまいましたよ、と orz



(追記)
コールバック関数でワンクッションおかなきゃいけない理由が分かりました。
JavaScriptの後方参照は、前回マッチした結果に対して行うようです。


【参考】
Javascript正規表現置換で後方参照を使いたい - 名もないテクノ手
http://d.hatena.ne.jp/seuzo/20090218/1234926645