4.2.6 例

scanf()をシミュレートする

Python には現在のところ、scanf()に相当するものがありません。 正規表現は、 scanf()のフォーマット文字列よりも、一般的に より強力であり、また冗長でもあります。以下の表に、 scanf() のフォーマットトークンと正規表現の 大体同等な対応付けを示します。

scanf() トークン 正規表現
%c .
%5c .{5}
%d [-+]?\d+
%e, %E, %f, %g [-+]?(\d+(\.\d*)?|\d*\.\d+)([eE][-+]?\d+)?
%i [-+]?(0[xX][\dA-Fa-f]+|0[0-7]*|\d+)
%o 0[0-7]*
%s \S+
%u \d+
%x, %X 0[xX][\dA-Fa-f]+

    /usr/sbin/sendmail - 0 errors, 4 warnings

のような文字列からファイル名と数値を抽出するには、

    %s - %d errors, %d warnings

のように scanf()フォーマットを使うでしょう。 それと同等な正規表現は

    (\S+) - (\d+) errors, (\d+) warnings

再帰を避ける

エンジンに大量の再帰を要求するような正規表現を作成すると、 maximum recursion limit exceeded(最大再帰制限を超過した) というメッセージを持つ RuntimeError 例外に出くわすかもしれません。たとえば、

>>> import re
>>> s = "Begin" + 1000 * 'a very long string' + 'end'
>>> re.match('Begin (\w| )*? end', s).end()
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "/usr/local/lib/python2.3/sre.py", line 132, in match
    return _compile(pattern, flags).match(string)
RuntimeError: maximum recursion limit exceeded

再帰を避けるように正規表現を組みなおせることはよくあります。

Python 2.3 からは、再帰を避けるために *? パターンの利用が 特別扱いされるようになりました。したがって、上の正規表現は Begin [a-zA-Z0-9_ ]*?end に書き直すことで再帰を防ぐことが できます。それ以上の恩恵として、そのような正規表現は、 再帰的な同等のものよりもより速く動作します。

ご意見やご指摘をお寄せになりたい方は、 このドキュメントについて... をご覧ください。