## 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` に書き直すことで再帰を防ぐことが できます。それ以上の恩恵として、そのような正規表現は、 再帰的な同等のものよりもより速く動作します。