環境
Python 3.5.2で検証
使用場面
正規表現による置換を行うとき,マッチした文字列に応じて置換する文字列を変化させたい場合
例として,以下のようなことができます.
- 文字列中にある数字に対して,何かしらの演算をした結果に置換したい
"abcd1234efg" -> "abcd2468efg" (数字を2倍) - 文字列中にある数字を漢数字に置換したい
"abcd1234efg" -> "abcd千二百三十四efg"
(上の例以外にも,より複雑な処理をさせることが可能だと思います)
方法
通常の正規表現による置換で使用するre.sub()
と,マッチした文字列に施したい処理を実装した関数を用います.
具体的には,re.sub(パターン, 関数, 検索する文字列)
とします.
上記で呼び出す関数の引数を仮にmatchobjとすると,関数内でmatchobj.group(0)とすることでパターンにマッチした文字列を利用できます.
def replace(matchobj):
s = matchobj.group(0)
# 行いたい処理
re.sub(`hoge`, replace, "sampletext")
実装例
下の例では,数字を漢数字に変換する関数toKansuji()
と,5%の消費税を8%に変更する関数fixTax()
を用意し,re.sub()内でマッチした数字に対して上記の関数を適用した結果に置換しています.
コード
import re
def toKansuji(matchobj):
a = ["一", "万", "億", "兆", "京"]
b = ["一", "十", "百", "千"]
c = ("", "一", "二", "三", "四", "五", "六", "七", "八", "九")
s = matchobj.group(0)
l = [int(i) for i in s]
result = ""
length = len(l)
for i in range(length):
n = l[length-1-i]
if i%4 == 0 and i//4 > 0:
az = 1
for j in range(4):
if l[length-1-i-j] != 0: az = 0
if az == 0: result = a[i//4] + result
if n != 0:
if i%4 != 0:
result = b[i%4] + result
if n != 1: result = c[n] + result
else:
result = c[n] + result
return result
def fixTax(matchobj):
d = int(matchobj.group(0))
d = int(d / 1.05 * 1.08)
return str(d)
if __name__ == '__main__':
s1 = "税込315円"
print("消費税5%:", s1)
print("消費税8%:", re.sub('\d+', fixTax, s1))
s2 = "IPv4は4294967296個"
print("数字 :", s2)
print("漢数字:", re.sub('\d{2,}', toKansuji, s2))
実行結果
消費税5%: 税込315円
消費税8%: 税込324円
数字 : IPv4は4294967296個
漢数字: IPv4は四十二億九千四百九十六万七千二百九十六個
上2行は消費税を5%から8%に,下2行は数字を漢数字に置換しています.
その他
パターンにおいて()を用いてグループ化すると,関数内でmatchobj.group(n)とすることでそのグループ内でマッチした文字列を利用することもできます.
(また,今回用意した関数はどちらも動作確認程度に用意したものなので,あらゆる入力に対して正確な値を返さないかもしれません)