Jinjaで正規表現置換フィルターを使用する

PythonのテンプレートエンジンJinjaで正規表現置換フィルター(regex_replace)を使ってみました。
2021.04.13

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。サービスグループの武田です。

PythonのテンプレートエンジンであるJinja、使ってますか?直接使ったことはなくてもAnsibleやFlaskを使ったことがあればお世話になっているはずです。さて、このエントリはJinjaで正規表現置換フィルターregex_replaceを使いたいという趣旨です。おそらく読者の中には「いやそれ使ったことあるよ?」という方もいるはずなのですが、それはAnsibleの話だと思われます。実際に「Jinja regex_replace」で検索するとヒットするのはほぼAnsibleの記事です(執筆時点)。

というわけで、素のJinjaでregex_replaceを使用するための手順を紹介します。

環境

次のような環境で検証しています。

$ sw_vers
ProductName:	Mac OS X
ProductVersion:	10.15.7
BuildVersion:	19H15

$ python3 -V
Python 3.9.1

$ pipenv --version
pipenv, version 2020.11.15

なお、Jinjaのバージョンは2.11.3でした。

やってみた

まずはプロジェクトを作成しJinjaをインストールします。

$ mkdir jinja2_regex_replace && cd $_
$ pipenv install jinja2

次に正規表現フィルターを使う簡単なコードを用意します。

main.py

from jinja2 import Environment

env = Environment()

text = "Hello, {{ name | regex_replace('s+', 'S') }}"

tpl = env.from_string(text)

msg = tpl.render({"name": "Classmethod"})

print(msg)

実行してみましょう。

$ pipenv run python main.py

jinja2.exceptions.TemplateAssertionError: no filter named 'regex_replace'

はい、想定どおりそんなフィルターは見つかりません。それでは自分で追加して使えるようにしてみましょう。コードを次のように修正します。

main.py

import re

from jinja2 import Environment

def regex_replace(s, pattern, replace):
    return re.sub(pattern, replace, s)

env = Environment()
env.filters["regex_replace"] = regex_replace

text = "Hello, {{ name | regex_replace('s+', 'S') }}"

tpl = env.from_string(text)

msg = tpl.render({"name": "Classmethod"})

print(msg)

フィルターといっても結局はPythonの関数です。正規表現置換するための関数を自分で定義します(5-6行目)。そしてその関数をregex_replaceという名前のフィルターとして登録します(9行目)。やることはこれだけです。あとは他のビルトインフィルターと同じようにテンプレート内で使えます!

実行してみましょう。

$ pipenv run python main.py

Hello, ClaSmethod

バッチリですね!

まとめ

regex_replaceで検索するとAnsibleばかりヒットするので、素のJinjaで使う方法を検証してみました。