zaki work log

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

Ansibleでsplitとjoinを使った文字列・配列操作

文字列を指定文字で分割して配列にバラすsplitと、配列を指定文字で結合して文字列に合成するjoinは、文字列と配列操作において大変有用。
主要なプログラミング言語には大抵この関数/メソッドは用意されており(※俺調べ)、フィルタ系の処理を書くときには重宝する。

qiita.com

Ansibleでこれらを活用するシチュエーションがどれくらいあるかはともかく、Ansibleでもsplitjoinを使うことができるのでその方法についてまとめ。
なお、環境はAnsible 2.10.5 時点。

split

Ansibleとしてはちょっとトリッキーかもしれないが、string型の変数に対してPythonstr#split()が使用できる。
時期バージョンではフィルターとしてsplitが使えるようになる模様

docs.python.org

  - name: split
    vars:
      string: 'tokyo, yokohama, fukuoka'
    debug:
      msg: "{{ string.split(',') }}"

実行結果

ok: [localhost] => 
  msg:
  - tokyo
  - ' yokohama'
  - ' fukuoka'

このとおり、,で分割して配列化できている。
が、,の後ろのスペースを除去できてないので配列要素にスペースが入っており綺麗な状態になっていない。

,の後ろの必ずスペース1文字しかないという書式であれば正規表現を使うまでもないが、そこが不明瞭であれば、やっぱり m/,\s*/ を使いたいところ。

Pythonstr#split()正規表現を直接指定できずreと連携する必要があるため、Ansibleから使うのはちょっと厳しい(やりかたがわからなかった)
なので一旦正規表現を使った文字列置換を一度行い、その後にsplitをすれば大体良い感じにできる。
(これは状況に因るので要件によって適切な方法を検討すること)

  - name: split
    vars:
      string: 'tokyo, yokohama, fukuoka,sapporo,  sendai, tokorozawa'
    debug:
      msg: "{{ (string | regex_replace(',\\s*', ',')).split(',') }}"

この例のように、対象文字列stringのデリミタで、,の後にスペースがあったりなかったり、あっても2つ以上のスペースだったり、、、という場合、regex_replaceを使って「綺麗に」してあげれば、実行結果は以下の通り。

ok: [localhost] => 
  msg:
  - tokyo
  - yokohama
  - fukuoka
  - sapporo
  - sendai
  - tokorozawa

余計なスペースが入っておらず、綺麗になった。

フィルターとしてのsplitについての情報はこちら。

github.com

join

Jinja2テンプレートのフィルタとして用意されているjoin()を使用できる。

jinja.palletsprojects.com

    - name: join sample
      vars:
        sample_items:
          - foo
          - bar
          - baz
      debug:
        msg: 
          - "{{ sample_items }}"
          - "{{ sample_items | join('<>') }}"

['foo', 'bar', 'baz']という配列に対して、joinを使って<>で連結」という内容。
実行すると以下の通り。

ok: [localhost] => 
  msg:
  - - foo
    - bar
    - baz
  - foo<>bar<>baz

まとめ

splitはファイルパスやURLの文字列を操作するためのsplit系フィルタは用意されてるが、任意の文字列に対する汎用処理を行うフィルタはない。ただし、Pythonのメソッドを使用することが可能。
joinはJinaj2のフィルタを使えばOK


splitjoinは(ログファイル解析などで)めっちゃ応用が利くので、インフラの人も正規表現とセットで覚えるべき。