正規表現にShift-JISをぶちこんだ時の注意

Shift-JISの文字コード体系では、2byte文字の2byte目にasciiコードが含まれることがあり、これを正規表現のpatternにそのまま使ってはまった件。
やりたいことは単純で、string.gsub()を使って文字列の中の単語を別の単語に置き換えると言う作業。

do
	local name_list = {}
	name_list["(キャラクター名1)"] = "主人公の助"
	name_list["(キャラクター名2)"] = "ライバルッチ"
	name_list["(キャラクター名3)"] = "ヒロイン子"
	name_list["(キャラクター名4)"] = "ボス"

	function replace_chara_name(str)
		for k, v in pairs(name_list) do
			str:gsub(k, v)
		end
		return str
	end

end

local text = "「なあ、(キャラクター名1)は元気にしてるのか?」"
text = replace_chara_name(text)
textwindow:write(text)

この時、"(キャラクター名)"の部分に(Luaの)メタ文字を含むShift-JIS文字があると、多くの場合そこでこけて死ぬ。メタ文字をそのとおりに解釈してしまうからだ。
メタ文字を文字そのものとして扱うには、"%"をつければいい。
なので、今後どんなメタ文字が出たとしても関係ないようにする。

string.kill_meta_chara = function(str)
	local temp = {}
	for i, v in ipairs({str:byte(1, str:len())}) do
		-- % は 37番
		temp[1+#temp] = 37
		temp[1+#temp] = v
	end
	return string.char(unpack(temp))
end
-- 全ての文字に%をつけてメタ文字否定をするメソッド

name_listのキーに対してこのメソッドで変換をかけると、完全な置き換え用正規表現パターンになる。

ひとりごと

NScripter2ならUTF8なんで、こういう問題は起こらないんだけどなー。