銀月の符号

Python 使い見習いの日記・雑記

Python レシピ追加、文字列の一部を特定の文字で埋める

「068:文字列の一部を特定の文字で埋める」を追加。

Ruby レシピブック 第2版 には Password: PythonRecipe のようなテキストを Password: ************ に置き換える例が載っていたので、これに則ったコードを。

# coding: utf-8

import re

def hide(pattern, string, rep=u'*', hide_group=1):
    u"""正規表現 pattern の hide_group 部分を rep に置き換える

    >>> hide(u'Password: (.*)', u'Password: PythonRecipe')
    u'Password: ************'
    >>> hide(u'ham', u'spam ham eggs', hide_group=0)
    u'spam *** eggs'
    >>> hide(ur'(?P<year>\d+)-(?P<month>\d{1,2})-(?P<day>\d{1,2})',
    ...      u'2009-12-09', hide_group='month')
    u'2009-**-09'
    """

    r = re.compile(pattern)

    m = r.search(string)
    if not m:
        raise ValueError(u'No match')

    start, end = m.span(hide_group)

    return u''.join([
        string[:start], (end - start) * rep, string[end:]])

def hide_password(string):
    u"""パスワード部分を隠す

    >>> hide_password(u'Password: PythonRecipe')
    u'Password: ************'
    """

    return hide(u'Password: (.*)', string)

hide 関数は汎用性を少しだけ意識している。

>>> hide(ur'(?P<year>\d+)-(?P<month>\d+)', u'2009-12', hide_group='month')
u'2009-**'
>>> hide(ur'(?P<year>\d+)-(?P<month>\d+)', u'2009-12', hide_group=0)
u'*******'

hide_group=['year', 'month'] のようにグループの複数指定をできるようにとか、グループにマッチ「しなかった」部分を置き換えたい、などなど、要求が増えるともう少し手を加えないといけなかったり。後で書く、かも。

re.compile をはじめとした re の関数は pattern 文字列の代わりに正規表現オブジェクトを渡しても動作するので、

>>> import re
>>> r = re.compile(u'spam')
>>> r is re.compile(r)  # すでに正規表現オブジェクトならオウム返し
True

hide 関数も正規表現オブジェクトを受け取ることができる。

>>> import re
>>> r = re.compile(u'(?P<year>\d+)-(?P<month>\d+)-(?P<day>\d+)')
>>> hide(r, u'2009-12-09', hide_group='day')
u'2009-12-**'