Question:
In Ansible, I have a list of strings that I want to join with newline characters to create a string, that when written to a file, becomes a series of lines. However, when I use the join() filter, it works on the inner list, the characters in the strings, and not on the outer list, the strings themselves. Here’s my sample code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
# Usage: ansible-playbook tst3.yaml --limit --- - hosts: all remote_user: root tasks: - name: Create the list set_fact: my_item: "{{ item }}" with_items: - "One fish" - "Two fish" - "Red fish" - "Blue fish" register: my_item_result - name: Extract items and turn into a list set_fact: my_list: "{{ my_item_result.results | map(attribute='ansible_facts.my_item') | list }}" - name: Examine the list debug: msg: "{{ my_list }}" - name: Concatenate the public keys set_fact: my_joined_list: "{{ item | join('\n') }}" with_items: - "{{ my_list }}" - name: Examine the joined string debug: msg: "{{ my_joined_list }}" |
I want to get output that looks like:
1 2 3 4 5 |
One fish Two fish Red fish Blue Fish |
What I get instead is:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
TASK: [Examine the joined string] ********************************************* ok: [hana-np-11.cisco.com] => { "msg": "B\nl\nu\ne\n \nf\ni\ns\nh" } ok: [hana-np-12.cisco.com] => { "msg": "B\nl\nu\ne\n \nf\ni\ns\nh" } ok: [hana-np-13.cisco.com] => { "msg": "B\nl\nu\ne\n \nf\ni\ns\nh" } ok: [hana-np-14.cisco.com] => { "msg": "B\nl\nu\ne\n \nf\ni\ns\nh" } ok: [hana-np-15.cisco.com] => { "msg": "B\nl\nu\ne\n \nf\ni\ns\nh" } |
How do I properly concatenate a list of strings with the newline character?
Answer:
Solution
join
filter works on lists, so apply it to your list:
1 2 3 4 |
- name: Concatenate the public keys set_fact: my_joined_list: "{{ my_list | join('\n') }}" |
Explanation
While my_list
in your example is a list, when you use with_items
, in each iterationitem
is a string. Strings are treated as lists of characters, thus join
splits them.
It’s like in any language: when you have a loop for i in (one, two, three)
and refer to i
inside the loop, you get only one value for each iteration, not the whole set.
Remarks
- Don’t use
debug
module, butcopy
withcontent
to have\n
rendered as newline. - The way you create a list is pretty cumbersome. All you need is (quotation marks are also not necessary):
12345678- name: Create the listset_fact:my_list:- "One fish"- "Two fish"- "Red fish"- "Blue fish"
join(‘\n’) is well and good, but just a wrning in that it does not add a newline to the end of the last entry.
Which with newlines is generally preferred.