はじめに
Ansible が内部で利用しているテンプレートエンジン Jinja2 には select
というフィルターがあります。(逆は reject
)
これまでは、Jinja2 公式ドキュメントの例のように、条件と一致する要素を抽出するものだと思っていました。
あるとき「指定した型を一致する要素を抽出できないものか」とおもったときに、こんな方法を教えていただきました。
リスト変数がaの時、これでできます(数値型のみ選択)
— Koji Hatanaka (@kojiha__) 2020年8月27日
{{ a | select('number') | list }}
他にもいくつの型で試してみましたので、結果をまとめます。
- 動作環境
- Ansible 2.9.9
- Jinja2 2.11.2
おためしPlaybook
以下のような Playbook で試します。
testlist
にいろいろな型を含めたリストを定義します。そのリストに対して、select
フィルターで number
や string
などの型を指定して抽出します。
指定できそうな型をしらべるときはこのあたりを見ました。
--- - hosts: localhost gather_facts: false vars: testlist: - true - 123 - "456" - "hello" - - "a" - "b" - k1: v1 k2: v2 tasks: - name: select test debug: msg: "{{ testlist | select(item) | list }}" loop: - number - integer - float - boolean - sequence - mapping
結果
実行結果です。
TASK [select test] *********************************** ok: [localhost] => (item=number) => { "msg": [ // true も抽出されたのが意外でした true 123 ] } ok: [localhost] => (item=integer) => { "msg": [ // 整数が抽出されました。"456" は文字列なので対象外。 123 ] } ok: [localhost] => (item=float) => { "msg": [] // 今回は float はなし } ok: [localhost] => (item=string) => { "msg": [ // 文字列が抽出つされました。"456" はやはり文字列。 "456", "hello" ] } ok: [localhost] => (item=boolean) => { "msg": [ // 予想通り true ] } ok: [localhost] => (item=sequence) => { "msg": [ // 意外な結果。 iterable なものはなんでも抽出されるよう "456", "hello", [ "a", "b" ], { "k1": "v1", "k2": "v2" } ] } ok: [localhost] => (item=mapping) => { "msg": [ // 予想通り { "k1": "v1", "k2": "v2" } ] }
おわりに
sequence
の結果が一番意外でした。本当にリストだけを抽出できる方法があれば知りたいです。
おまけ情報ですが、サンプル Playbook にある | list
は ansible 2.10 から不要になります。