# How to generate a list of formatted strings

**URL:** <https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198>\
**Category:** Get Help\
**Tags:** variables, jinja2\
**Created:** [February 11, 2025, 11:08pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198 "2025-02-11T23:08:35Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![ianhinder](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/ianhinder/32/7559_2.png) [@ianhinder](https://forum.ansible.com/u/ianhinder)\
**Post date:** [February 11, 2025, 11:08pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/1 "2025-02-11T23:08:35Z")

</div>

I would like to define a variable called test\_users with a list of test usernames:

```auto
test_users:
  - testuser_001
  - testuser_002
  ...
  - testuser_100

```

I would prefer not to type them in by hand, or generate the list and paste it into the YAML file. I imagined that I could do something like

```auto
test_users: "{{ range(1, 100, 1) | format('testuser_%3d') | list }}"

```

but this doesn’t work, as the format filter takes the format string as input rather than the item(s) to be formatted.

What would be a good way to achieve this?

Thanks!

---

<div class="post-metadata">

**Author:** ![markuman](https://avatars.discourse-cdn.com/v4/letter/m/7bcc69/32.png) [@markuman](https://forum.ansible.com/u/markuman)\
**Post date:** [February 12, 2025, 9:59am UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/2 "2025-02-12T09:59:38Z")

</div>

[https://docs.ansible.com/ansible/latest/playbook\_guide/playbooks\_filters.html#searching-strings-with-regular-expressions](https://docs.ansible.com/ansible/latest/playbook_guide/playbooks_filters.html#searching-strings-with-regular-expressions)

Below is a section with

> To replace text in a string with regex, use the [ansible.builtin.regex\_replace](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/regex_replace_filter.html#ansible-collections-ansible-builtin-regex-replace-filter) filter:

```yml
---
- hosts: localhost
  tasks:
    - debug:
        var: range(1, 10) | map('regex_replace', '^', 'testuser_') | list 

```

results in

```auto
ok: [localhost] => {
    "range(1, 10) | map('regex_replace', '^', 'testuser_') | list": [
        "testuser_1",
        "testuser_2",
        "testuser_3",
        "testuser_4",
        "testuser_5",
        "testuser_6",
        "testuser_7",
        "testuser_8",
        "testuser_9"
    ]
}

```

---

<div class="post-metadata">

**Author:** ![ianhinder](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/ianhinder/32/7559_2.png) [@ianhinder](https://forum.ansible.com/u/ianhinder)\
**Post date:** [February 12, 2025, 2:00pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/3 "2025-02-12T14:00:47Z")

</div>

Thanks - that’s a good option. Do you know if there is a way to get the zero-padding? That’s less important, but I thought it should be doable with Jinja. It’s a shame the format function can’t be used for this.

---

<div class="post-metadata">

**Author:** ![ianhinder](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/ianhinder/32/7559_2.png) [@ianhinder](https://forum.ansible.com/u/ianhinder)\
**Post date:** [February 12, 2025, 2:20pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/4 "2025-02-12T14:20:36Z")

</div>

I found another option:

```auto
      test_users: "{{ (['testuser_%03d'] * 10) | join(',') | format(*range(1,11)) | split(',') }}"

```

inspired by [this answer](https://stackoverflow.com/a/77401062). It lacks elegance because it requires you to keep the number of format strings and the length of the range the same, and it goes via strings, so you have to be careful that your separator doesn’t appear in the string, but it does the job in a single line without having to make a custom filter. Is there a way to improve on this?

---

<div class="post-metadata">

**Author:** ![markuman](https://avatars.discourse-cdn.com/v4/letter/m/7bcc69/32.png) [@markuman](https://forum.ansible.com/u/markuman)\
**Post date:** [February 12, 2025, 2:25pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/5 "2025-02-12T14:25:26Z")

</div>

> [@markuman](#):
>
> ```auto
> ['testuser_%03d'] * 10
> 
> ```

this remembers me back to old times with gnu octave.

Another possibility when you process the variable item after item…

```yml
    - debug:
        var: USER 
      vars:
        USER: "{{ 'testuser_%03d' | format(item) }}"
      loop: "{{ range(1,100) }}"

```

Instead of `debug`, you can use `include_tasks: some_taskfile.yml` and work with the `USER` var.

---

<div class="post-metadata">

**Author:** ![ianhinder](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/ianhinder/32/7559_2.png) [@ianhinder](https://forum.ansible.com/u/ianhinder)\
**Post date:** [February 12, 2025, 2:45pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/6 "2025-02-12T14:45:50Z")

</div>

Yeah, the task loop is what I started with, but I actually do need this as a list variable, because it will be joined to another list.

Thanks!

---

<div class="post-metadata">

**Author:** ![sivel](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/sivel/32/1198_2.png) [@sivel](https://forum.ansible.com/u/sivel)\
**Post date:** [February 12, 2025, 3:21pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/7 "2025-02-12T15:21:10Z")

</div>

What you need to be able to use is the `map` filter, but unfortunately the built in jinja2 `format` filter wasn’t really written with usability from the `map` filter in mind, and thus the arguments it takes are reversed from what you need.

Instead of making some overly complicated jinja template in your playbook, I’d recommend making a new custom filter for your needs. This could be as simple as making your own version of `format` that works the way you need such as:

```python
# saved as filter_plugins/ianhinder.py
def ianhinder_format(value, fmt):
    return fmt % value

class FilterModule:
    def filters(self):
        return {
            'ianhinder_format': ianhinder_format,
        }

```

And then a task to use it:

```yaml
    - debug:
        msg: "{{ range(1, 101, 1) | map('ianhinder_format', 'testuser_%03d') }}"

```

**Note** : Needed to use `%03d` instead of `%3d` since the latter does space padding and not zero padding. And to include `100` in the range, you have to set the `stop` to `101` as it’s not inclusive of the `stop`.

Produces:

```auto
ok: [localhost] => {
    "msg": [
        "testuser_001",
        "testuser_002",
        "testuser_003",
        "testuser_004",
        "testuser_005",
        "testuser_006",
        "testuser_007",
        "testuser_008",
[SNIP]
        "testuser_100"
    ]
}

```

---

<div class="post-metadata">

**Author:** ![ianhinder](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/ianhinder/32/7559_2.png) [@ianhinder](https://forum.ansible.com/u/ianhinder)\
**Post date:** [February 12, 2025, 9:47pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/8 "2025-02-12T21:47:01Z")

</div>

Thanks. That certainly is the most ergonomic in the playbook, though it has the annoyance of having to implement it yourself. Yes, most of the examples I found for similar tasks when searching said you need to write your own filter in Python. It seems that Jinja2 is not quite powerful enough to express all that is generally needed, and it needs to be augmented with Python code even for quite simple use cases.

---

<div class="post-metadata">

**Author:** ![chris](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/chris/32/293_2.png) [@chris](https://forum.ansible.com/u/chris)\
**Post date:** [February 12, 2025, 10:58pm UTC](https://forum.ansible.com/t/how-to-generate-a-list-of-formatted-strings/40198/9 "2025-02-12T22:58:09Z")

</div>

I’d be tempted to use the [ansible.builtin.regex\_replace filter](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/regex_replace_filter.html) for this… 🤷
