zaki work log

作業ログやら生活ログやらなんやら

[Ansible] intフィルターで16進数表記の文字列を基数変換

AnsibleではJinja2のint()フィルターで文字列を整数へ変換できるが、0xdeadbeafみたいな16進数表記の文字列をint(base=16)のようにパラメタを指定することで基数変換することもできる。

16進表記の文字列を比較する処理を使う機会があったのでまとめ。

確認した環境は以下の通り。

(a2.10) [zaki@cloud-dev filter (master)]$ ansible --version
ansible 2.10.5
  config file = /home/zaki/src/ansible-sample/filter/ansible.cfg
  configured module search path = ['/home/zaki/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/zaki/src/ansible-sample/venv/a2.10/lib64/python3.6/site-packages/ansible
  executable location = /home/zaki/src/ansible-sample/venv/a2.10/bin/ansible
  python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

int(base=16)

16進数表記の文字列をintegerに変換。

  - name: hex to dec
    vars:
      hex_values:
      - '0xa'
      - '0x0a'
      - '0xff'
      - '0xffff'
      - '0xdeadbeaf'
      - '0b0'  # 0x0b0 
      - 'b'    # 0x0b
      - 'ff'   # 0xff
      - 'z'    # 0
      - '0o11' # 0
    debug:
      msg: "{{ item | int(base=16) }}"
    with_items: "{{ hex_values }}"

実行結果は以下の通り。

TASK [hex to dec] *************************************************************
ok: [localhost] => (item=0xa) => 
  msg: '10'
ok: [localhost] => (item=0x0a) => 
  msg: '10'
ok: [localhost] => (item=0xff) => 
  msg: '255'
ok: [localhost] => (item=0xffff) => 
  msg: '65535'
ok: [localhost] => (item=0xdeadbeaf) => 
  msg: '3735928495'
ok: [localhost] => (item=0b0) => 
  msg: '176'
ok: [localhost] => (item=b) => 
  msg: '11'
ok: [localhost] => (item=ff) => 
  msg: '255'
ok: [localhost] => (item=z) => 
  msg: '0'
ok: [localhost] => (item=0o11) => 
  msg: '0'

16進表記になっていない文字列は0になっている。
2進数表記の0b00b01010101のような文字列を変換すると、2進数でなく0xがあるとみなされた16進数として処理されるので注意。

int(baes=8)

8進数表記の文字列をintegerに変換。

  - name: oct to dec
    vars:
      oct_values:
      - '0o11'
      - '77'   # 0o77 -> 63
      - 'z'    # 0
      - '0x0a' # 0
    debug:
      msg: "{{ item | int(base=8) }}"
    with_items: "{{ oct_values }}"

実行結果は以下の通り。

TASK [oct to dec] *************************************************************
ok: [localhost] => (item=0o11) => 
  msg: '9'
ok: [localhost] => (item=77) => 
  msg: '63'
ok: [localhost] => (item=z) => 
  msg: '0'
ok: [localhost] => (item=0x0a) => 
  msg: '0'

そのまま。

int(base=2)

2進数表記の文字列をintegerに変換。

  - name: bin to dec
    vars:
      bin_values:
      - '0b11'
      - '101'  # 0b101 -> 5
      - 'z'    # 0
      - '0x0a' # 0
    debug:
      msg: "{{ item | int(base=2) }}"
    with_items: "{{ bin_values }}"

実行結果は以下の通り。

TASK [bin to dec] *************************************************************
ok: [localhost] => (item=0b11) => 
  msg: '3'
ok: [localhost] => (item=101) => 
  msg: '5'
ok: [localhost] => (item=z) => 
  msg: '0'
ok: [localhost] => (item=0x0a) => 
  msg: '0'

参考

jinja.palletsprojects.com

int(value, default=0, base=10)

You can also override the default base (10) in the second parameter, which handles input with prefixes such as 0b, 0o and 0x for bases 2, 8 and 16 respectively.

サンプル

github.com


(´-`).。oO(これintegerにしてるだけだし基数変換って言って良いのかな…