Search code examples
stringansibleuntil-loop

Ansible best practice for breaking a string into a list of max length substrings?


This shows what I am trying to do

---
- hosts: localhost
  gather_facts: false
  vars:
    str: "abcdefg"
    str_parts: []
  tasks:
    - name: Break string into list of max 3 character parts
      set_fact:
        str_parts: "{{ str_parts + [ str[:3] ] }}"
        str: "{{ str[3:] }}"
      until: str == ""

Running it with -vvv shows the loop code is executed only once. str_parts gains single member "abc", str is changed to "defg" and the log shows "FAILED - RETRYING: Break string into list of max 3 character parts" messages until it times out

Why doesn't the loop, er, loop?

I could solve it by using a command or shell module to insert commas at the break points and then using {{ str | split(",") }} but a pure Ansible solution would be nicer

Edit: the behavior the subject of bug set_fact won't update a fact while looping (breaking change)


Solution

  • For example

        - set_fact:
            str_parts: "{{ str|batch(3)|map('join') }}"
    

    gives

      str_parts:
      - abc
      - def
      - g
    

    It is possible to select matching items only, e.g.

        - set_fact:
            str_parts: "{{ str|batch(3)|map('join')|select('match', '^.{3}$') }}"
    

    gives

      str_parts:
      - abc
      - def