Formatting multiple lines using variable as loop

66 views
Skip to first unread message

Veera

unread,
Dec 14, 2023, 5:50:15 AM12/14/23
to Ansible Project
I have a playbook variable output as below


debug:
  msg: "{{my_var}}}"
 
TASK [debug] **************************************************************************************************************************
ok: [localhost] => {
    "msg": [
        "line1 has , color-red, in  its   middle"
        "line2 has,   color-blue,   in its middle"
        "line3 has,  color-orange, in its middle"
    ]
}


I want to use the output lines as  an input for another variable using set_fact , as like below .

  - name: Filtering  the color data  
    ansible.builtin.set_fact:
      new_var: "{{ item.split(',')[1] }}"
loop: "{{ var1 }}"

and I am looking for the data like below
  color-red
  color-blue
  color-orange

 - debug: 
     var:  new_var
gives only color-red
 
 But my  var1 looping process the first line only in from the my_var and not the next 2 lines.
 This is an example and I may expect lines from my_var from 0 to 100's.

How to print the column[]of output) with multiple lines ??

Todd Lewis

unread,
Dec 14, 2023, 4:14:45 PM12/14/23
to ansible...@googlegroups.com, uto...@gmail.com

In the code below, note that "range(my_var | length)" is equivalent to "[0, 1, 2]".

In the set_fact, we don't "loop" the task; rather we loop over the data within the jinja2 expression by using the map filter.

utoddl@tango:~/ansible$ cat veera01.yml
---
# veera01.yml
- name: Jinja expressions
  hosts: localhost
  gather_facts: false
  vars:
    my_var:
      - "line1 has , color-red, in  its   middle"
      - "line2 has,   color-blue,   in its middle"
      - "line3 has,  color-orange, in its middle"
  tasks:
    - name: Split and trim parts from my_var
      ansible.builtin.debug:
        msg: "{{ my_var | map('split', ',') | map('map', 'trim') }}"

    - name: Extract the "color-*" parts from my_var
      ansible.builtin.debug:
        msg: "{{ range(my_var | length) | map('extract', (my_var | map('split', ',') | map('map', 'trim')), [1]) }}"

    - name: Same but as set_fact
      ansible.builtin.set_fact:
        new_var: "{{ range(my_var | length) | map('extract', (my_var | map('split', ',') | map('map', 'trim')), [1]) }}"


utoddl@tango:~/ansible$ ansible-playbook veera01.yml -v
Using /etc/ansible/ansible.cfg as config file

PLAY [Jinja expressions] **********************************************

TASK [Split and trim parts from my_var] *******************************
ok: [localhost] => 
  msg:
  - - line1 has
    - color-red
    - in  its   middle
  - - line2 has
    - color-blue
    - in its middle
  - - line3 has
    - color-orange
    - in its middle

TASK [Extract the "color-*" parts from my_var] ************************
ok: [localhost] => 
  msg:
  - color-red
  - color-blue
  - color-orange

TASK [Same but as set_fact] *******************************************
ok: [localhost] => changed=false 
  ansible_facts:
    new_var:
    - color-red
    - color-blue
    - color-orange

PLAY RECAP ************************************************************
localhost                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

--
You received this message because you are subscribed to the Google Groups "Ansible Project" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ansible-proje...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/ansible-project/3490a8af-689c-4cb1-8670-1495258df226n%40googlegroups.com.

-- 
Todd
Message has been deleted

Veera

unread,
Dec 15, 2023, 12:15:18 PM12/15/23
to Ansible Project
Hi  Todd Lewis,

Thanks . I am able to understand it . However the split happens based on ',' , and then we remove the quotes with  map('map', 'trim')) and align the lines with range.
However assuming split with delimiter as comma,  when i try to replace 1 with 0  the output is  [msg: "{{ range(my_var | length) | map('extract', (my_var | map('split', ',') | map('map', 'trim')), [0]) }}"]
 
ok: [localhost] =>
  msg:
  - line1 has
  - line2 has
  - line3 has


and when tried to add [0 1] in the  end  [msg: "{{ range(my_var | length) | map('extract', (my_var | map('split', ',') | map('map', 'trim')), [0 1]) }}"]
it printsok: [localhost] =>
  msg:
  - i
  - i
  - i
that is second character in the word line[0]. Is not the split breaks the words  with (',')?
How to print all the available column? instead of 1( yes the full  file without a comma now )
Actually I am trying to print like below

line1 has  color-red
line2 has  color-blue  
line3 has  color-orange

On Friday, December 15, 2023 at 10:42:43 PM UTC+5:30 Veera wrote:
Hi  Todd Lewis,

Thanks . I am able to understand it . However the split happens based on ',' , and then we remove the quotes with  map('map', 'trim')) and align the lines with range.
However assuming split with delimiter as comma,  when i try to replace 1 with 0  the output is  [msg: "{{ range(my_var | length) | map('extract', (my_var | map('split', ',') | map('map', 'trim')), [1]) }}"]
 
ok: [localhost] =>
  msg:
  - line1 has
  - line2 has
  - line3 has


and when tried to add [0 1] in the  end  [msg: "{{ range(my_var | length) | map('extract', (my_var | map('split', ',') | map('map', 'trim')), [0 1]) }}"]
it printsok: [localhost] =>
  msg:
  - i
  - i
  - i
that is second character in the word line[0]. Is not the split breaks the words  with (',')?
How to print all the available column? instead of 1( yes the full  file without a comma now )
Actually I am trying to print like below
 line1 has  color-red
line2 has color-blue  
line3 has, color-orange

Todd Lewis

unread,
Dec 15, 2023, 3:00:25 PM12/15/23
to ansible...@googlegroups.com, uto...@gmail.com
You said, "However the split happens based on ',' , and then we remove the quotes with  map('map', 'trim')) and align the lines with range."

It's true that "split(',')" will split a string containing commas into a list of strings. But the trim filter does nothing with quotes.

Rather, "trim" removes leading and trailing spaces from the string piped into it:
  a_string | trim

Further, "map('trim')" removes leading and trailing spaces from each string of the list of strings passed to it:
  [str0, str1, str2] | map('trim')

Finally, "map('map', 'trim')" trims strings two levels deep in lists:
  [[sa0, sa1], [sb0, bs1], [sc0, sc1]] | map('map', 'trim')

Quotes never play into it. In fact, in what you initially posted, and in my response, the string data contain no quotes.

Also, "range" isn't to align anything. It provides the necessary first parameter to the "extract" filter.

However assuming split with delimiter as comma,  when i try to replace 1 with 0  the output is  [msg: "{{ range(my_var | length) | map('extract', (my_var | map('split', ',') | map('map', 'trim')), [0]) }}"]
Yes, you changed the "1" to a "0", so you get the first (index=0) item in the list produced by the split.

When it was "1", you got the second item (index=1) in each list produced by the split, that is "color-red", "color-blue", and "color-orange". From your initial post, that's what I thought you wanted.

If what you really want is this:
    new_var:
    - line1 has color-red
    - line2 has color-blue
    - line3 has color-orange
then you can use this instead:
    - name: First and Second parts from split on comma
      ansible.builtin.set_fact:
        new_var: "{{ my_var | map('regex_replace', '^([^,]*),([^,]*),.*', '\\1 \\2') | map('regex_replace', ' +', ' ') }}"

Veera

unread,
Dec 16, 2023, 1:25:43 AM12/16/23
to Ansible Project
Thanks Todd for the details ...
Reply all
Reply to author
Forward
0 new messages