読者です 読者をやめる 読者になる 読者になる

Python における正規表現と sqlite3 への接続

Python を用いて web サイトを構築するにあたり,sqlite3 で作成したデータベースにアクセスすることがある.
このとき,sqlite3 における特殊文字の表現と Python における正規表現を明確に区別しておかないと,おかしな挙動を示すことになる.

Pythonにおける正規表現を挙げる.

. ワイルドカード
^ 行頭
$ 行末
直前の文字がないか,もしくは一つ以上ある
+ 直前の文字が一つ以上ある
? 直前の文字がないか,または一つだけある
[] 指定した文字のどれか
いずれかの文字
() グループ化

これらの文字がsqlite3に保存されている場合,直接文字を指定してアクセスするとエラーを返す場合が多いはず.
そこで,これらの文字をPython内で単なる文字として扱う場合,バックスラッシュを付加すると良い.
つまり,\? のようにする.

そのためのメソッド.

import re

def escape(self, s, quoted=u'.^$*+?', escape=u"\\":
    return re.sub(u'[%s]' % re.escape(quoted), lambda mo: escape + mo.group(), s)

sが対象の文字列,quoted に変換したい特殊文字を指定,escapeに特殊文字に追加する文字を指定.
上の例では, .^$*+? を \.\^\$\*\+\? にしている.

たとえば,"?joker+phoenix*"なんて文字があって,これをそのまま扱いたい場合,

str = "?joker+phoenix*"
str_unicode = unicode(str, 'utf-8')
str_escape = self.escape(str_unicode, quoted=u".^$*+?[]|()", escape=u"\\")
print str_escape
---
\?joker\+phoenix\*

となる.

さて,sqlite3 ではこういった特殊文字はどうなのか?
これはあまり詳しくないけれど,とりあえず,シングルクォーテーションは重ねておかないといけないようだ.

I'm a machine.

なんて言葉は

I''m a machine.

として保存されている.

だから,Python から sqlite3 に文字列を渡す場合,シングルクォーテーションは重ねておく必要がある.
よって,あらかじめ

str = self.escape(str, quoted=u"'", escape=u"'")

のように変更しておこう.
とりあえず,今のところ,これで幸せ.