Python でタグ付き正規表現を replace する(後方参照を用いたreplace)
たとえば以下のような文字列があったとして、
"hoge **fuga** test piyo"
この **fuga**
部分を <strong>fuga</strong>
に置き換えたいとする。
さてどうやる?
アプローチ
まず対象は正規表現と探すとして、問題は 置換後の文字列をどうやって書くか である。ここは「ヒットしたパターンそのもの(ここでは fuga
)を引用したい」のではなかろうか。
そういうのを実現するのが タグ付き正規表現 とか 後方参照 とか呼ばれる技術で、要するに ()
でマッチした部分を \1
とか \2
とかで参照できる機能。正規表現ライブラリはたいていサポートしていて、Python の re もサポートしていたので、使ってみた。
スクリプト
何とかできた。 match オブジェクト との格闘だったかな。
import re def get_all_taginfo(original_string, re_pattern): compiled_obj = re.compile(re_pattern) iters = compiled_obj.finditer(original_string) all_taginfo = [] for matchobj in iters: matched_string = None tags = [] total = len(matchobj.groups()) startpos, endpos = matchobj.span() matched_string = original_string[startpos:endpos] for idx in range(total): tag = matchobj.groups()[idx] tags.append(tag) taginfo = { 'matched_string' : matched_string, 'tags' : tags, } all_taginfo.append(taginfo) return all_taginfo def replace_bold_pattern(original_string): pattern = r'\*\*([^\*]+)\*\*' all_taginfo = get_all_taginfo(original_string, pattern) replaced_string = original_string for taginfo in all_taginfo: tag1 = taginfo['tags'][0] before = taginfo['matched_string'] after = '<strong>{:}</strong>'.format(tag1) replaced_string = replaced_string.replace(before, after) return replaced_string def replace_all(original_string): replaced_string = original_string replaced_string = replace_bold_pattern(replaced_string) return replaced_string original = "hoge **fuga** test piyo" after = replace_all(original) print(after) # hoge <strong>fuga</strong> test piyo
スクリプト要約
まずは finditer()
でマッチオブジェクトを全部集めてくる。
置換前文字列はマッチオブジェクトの span()
を使えば取れる。
置換後文字列はマッチオブジェクトの groups()
から後方参照を全部取ってきた後、適当に整形すればいい。