# Ansible for loop on csv file, break out title line

**URL:** <https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165>\
**Category:** Ansible Project\
**Tags:** ubuntu\
**Created:** [November 29, 2017, 1:52pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165 "2017-11-29T13:52:28Z")\
**Posts on this page:** 15\
**Page:** 1

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [November 29, 2017, 1:52pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/1 "2017-11-29T13:52:28Z")

</div>

I have a playbook where I am using csv file to create a vars file. The for loop iterates through the csvfile, skips the first title line then splits each line into a list. Works fine, but I was hoping to instead of skipping the title line, to pull out the names and use as the variable name instead of hard coding the names like Type, Hostname, etc. This would allow me to input csv files that have different title names and more or less names.

csv file example:

```auto
Type,Hostname,IP_Address,Gateway,DNS_Server,NTP_Server
ubuntu,lab1,10.1.1.1,10.1.1.254,192.168.1.254.192.168.1.253
centos,lab2,10.1.1.2,10.1.1.254,192.168.1.254.192.168.1.253
rhel6,lab3,10.1.1.3,10.1.1.254,192.168.1.254.192.168.1.253
rhel7,lab4,10.1.1.4,10.1.1.254,192.168.1.254.192.168.1.253

```

loop code:

```auto
---
servers:
{% for item in csvfile.split("\n") %}
{% if loop.index != 1 %}
{% set list = item.split(",") %}
  {{ list[1]|trim() }}:
    Type: {{ list[0]|trim() }}
    Hostname: {{ list[1]|trim() }}
    IP_Address: {{ list[2]|trim() }}
    Gateway: {{ list[3]|trim() }}
    DNS_Server: {{ list[4]|trim() }}
    NTP_Server: {{ list[22]|trim() }}
{% endif %}
{% endfor %}

```

Question I have is, how would I pull out loop.index. 1 and use the title names as variables? Something like this:

```auto
{{ title. }}: {{ list[0]|trim() }}
{{ title. }}: {{ list[1]|trim() }}
{{ title }}: {{ list[2]|trim() }}
{{ title }}: {{ list[3]|trim() }}
{{ title }}: {{ list[4]|trim() }}
{{ title }}: {{ list[22]|trim() }}

```

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [December 1, 2017, 4:26pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/2 "2017-12-01T16:26:15Z")

</div>

Can't you just do something like this?

{% if loop.index == 1 %}  
{% set title = item.split(',') %}  
{% endif %}

Then you can use title[0], title[1]...

---

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [December 1, 2017, 5:08pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/3 "2017-12-01T17:08:15Z")

</div>

I tried, but the title variable does not keep when looping from second row and on.

{% for item in csvfile.split(“\n”) %}  
{% if loop.index == 1 %}  
{% set title = item.split(‘,’) %}  
{% else %}  
{% set list = item.split(“,”) %}  
{{ list[1]|trim() }}:  
{{ title[0] }}: {{ list[0]|trim() }}  
{{ title[1] }}: {{ list[1]|trim() }}  
{{ title[2] }}: {{ list[2]|trim() }}  
{{ title[3] }}: {{ list[3]|trim() }}  
{{ title[4] }}: {{ list[4]|trim() }}  
{{ title[5] }}: {{ list[5]|trim() }}  
{% endif %}

{% endfor %}

The playbook output for task

TASK [Parse CSV To YAML] \*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*  
fatal: [localhost]: FAILED! =\> {“changed”: false, “failed”: true, “msg”: “AnsibleUndefinedVariable: ‘title’ is undefined”}

msg: AnsibleUndefinedVariable: ‘title’ is undefined

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [December 1, 2017, 6:16pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/4 "2017-12-01T18:16:19Z")

</div>

That's strange since the Jinja documentation have the following about scope:  
"Please keep in mind that it is not possible to set variables inside a block and have them show up outside of it.  
This also applies to loops. The only exception to that rule are if statements which do not introduce a scope."

Maybe it's a bug.

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [December 1, 2017, 7:04pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/5 "2017-12-01T19:04:38Z")

</div>

As a workaround since this i a scope issue, you could set the title outside of the for loop.

&nbsp;&nbsp;{% set title = csvfile.split("\n")[0].split(',') %}  
&nbsp;&nbsp;{% for item in csvfile.split("\n")[1:] %}  
&nbsp;&nbsp;{% set list = item.split(",") %}  
&nbsp;&nbsp;{{ list[1]|trim() }}:  
&nbsp;&nbsp;{{ title[0] }}: {{ list[0]|trim() }}  
&nbsp;&nbsp;{{ title[1] }}: {{ list[1]|trim() }}  
&nbsp;&nbsp;{{ title[2] }}: {{ list[2]|trim() }}  
&nbsp;&nbsp;{{ title[3] }}: {{ list[3]|trim() }}  
&nbsp;&nbsp;{{ title[4] }}: {{ list[4]|trim() }}  
&nbsp;&nbsp;{{ title[5] }}: {{ list[5]|trim() }}  
&nbsp;&nbsp;{% endfor %}

---

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [December 1, 2017, 8:25pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/6 "2017-12-01T20:25:53Z")

</div>

Works perfectly! Thank you so much Kai Stian.

---

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [December 1, 2017, 9:31pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/7 "2017-12-01T21:31:42Z")

</div>

I do have one more question. Say I am not sure if the last list[6] variable is defined, how would I write that? I tried the below but did not work.

{% set title = csvfile.split(“\n”)[0].split(‘,’) %}  
{% for item in csvfile.split(“\n”)[1:] %}  
{% set list = item.split(“,”) %}  
{{ list[1]|trim() }}:  
{{ title[0] }}: {{ list[0]|trim() }}  
{{ title[1] }}: {{ list[1]|trim() }}  
{{ title[2] }}: {{ list[2]|trim() }}  
{{ title[3] }}: {{ list[3]|trim() }}  
{{ title[4] }}: {{ list[4]|trim() }}  
{{ title[5] }}: {{ list[5]|trim() }}

{% if {{ list[6] }} %}  
{{ title[6] }}: {{ list[6]|trim() }}

{% endif %}  
{% endfor %}

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [December 1, 2017, 9:40pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/8 "2017-12-01T21:40:41Z")

</div>

You can't use {{ }} inside then template code, since you are in template mode it understand that list[6] is a variable.  
Try this

{% if list[6] is defined %}  
&nbsp;&nbsp;&nbsp;&nbsp;{{ title[6] }}: {{ list[6]|trim() }}  
{% endif %}

---

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [December 1, 2017, 9:54pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/9 "2017-12-01T21:54:49Z")

</div>

That worked, thanks again for you help.

---

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [December 3, 2017, 1:18am UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/10 "2017-12-03T01:18:11Z")

</div>

Sorry, one more thing. I want to identify if the title equals Hostname and both the title and list index match. I have it working below, but was hoping there is a cleaner way of doing this.

{% set title = csvfile.split(“\n”)[0].split(‘,’) %}

{% for item in csvfile.split(“\n”)[1:] %}  
{% set list = item.split(“,”) %}

{% if title[0] == “Hostname” and list[0] %}  
{{ list[0]|trim() }}:  
{% elif title[1] == “Hostname” and list[1] %}  
{{ list[1]|trim() }}:  
{% elif title[1] == “Hostname” and list[1] %}  
{{ list[1]|trim() }}:  
{% elif title[2] == “Hostname” and list[2] %}  
{{ list[2]|trim() }}:  
{% elif title[3] == “Hostname” and list[3] %}  
{{ list[3]|trim() }}:  
{% elif title[4] == “Hostname” and list[4] %}  
{{ list[4]|trim() }}:  
{% elif title[5] == “Hostname” and list[5] %}  
{{ list[5]|trim() }}:  
{% endif %}

{{ title[0] }}: {{ list[0]|trim() }}  
{{ title[1] }}: {{ list[1]|trim() }}  
{{ title[2] }}: {{ list[2]|trim() }}  
{{ title[3] }}: {{ list[3]|trim() }}  
{{ title[4] }}: {{ list[4]|trim() }}  
{{ title[5] }}: {{ list[5]|trim() }}  
{% endfor %}

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [December 3, 2017, 1:46pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/11 "2017-12-03T13:46:09Z")

</div>

> Sorry, one more thing. I want to identify if the title equals Hostname and  
> both the title and list index match.

I don't understand what your mean, could you rephrase.

> I have it working below, but was  
> hoping there is a cleaner way of doing this.
> 
> {% set title = csvfile.split("\n")[0].split(',') %}  
> &nbsp;&nbsp;{% for item in csvfile.split("\n")[1:] %}  
> &nbsp;&nbsp;{% set list = item.split(",") %}
> 
> &nbsp;&nbsp;{% if title[0] == "Hostname" and list[0] %}  
> &nbsp;&nbsp;&nbsp;&nbsp;{{ list[0]|trim() }}:  
> &nbsp;&nbsp;{% elif title[1] == "Hostname" and list[1] %}  
> &nbsp;&nbsp;&nbsp;&nbsp;{{ list[1]|trim() }}:  
> &nbsp;&nbsp;{% elif title[1] == "Hostname" and list[1] %}  
> &nbsp;&nbsp;&nbsp;&nbsp;{{ list[1]|trim() }}:  
> &nbsp;&nbsp;{% elif title[2] == "Hostname" and list[2] %}  
> &nbsp;&nbsp;&nbsp;&nbsp;{{ list[2]|trim() }}:  
> &nbsp;&nbsp;{% elif title[3] == "Hostname" and list[3] %}  
> &nbsp;&nbsp;&nbsp;&nbsp;{{ list[3]|trim() }}:  
> &nbsp;&nbsp;{% elif title[4] == "Hostname" and list[4] %}  
> &nbsp;&nbsp;&nbsp;&nbsp;{{ list[4]|trim() }}:  
> &nbsp;&nbsp;{% elif title[5] == "Hostname" and list[5] %}  
> &nbsp;&nbsp;&nbsp;&nbsp;{{ list[5]|trim() }}:  
> &nbsp;&nbsp;{% endif %}

To me, it looks like this code just print out the value correspond to the "Hostname".  
If that is the goal, then this for loop does that.

&nbsp;&nbsp;&nbsp;{% for element in range(list | count) %}  
&nbsp;&nbsp;&nbsp;{% if title[element] == "Hostname" %}  
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{{ list[element]|trim }}:  
&nbsp;&nbsp;&nbsp;{% endif %}  
&nbsp;&nbsp;&nbsp;{% endfor %}

> &nbsp;&nbsp;{{ title[0] }}: {{ list[0]|trim() }}  
> &nbsp;&nbsp;{{ title[1] }}: {{ list[1]|trim() }}  
> &nbsp;&nbsp;{{ title[2] }}: {{ list[2]|trim() }}  
> &nbsp;&nbsp;{{ title[3] }}: {{ list[3]|trim() }}  
> &nbsp;&nbsp;{{ title[4] }}: {{ list[4]|trim() }}  
> &nbsp;&nbsp;{{ title[5] }}: {{ list[5]|trim() }}

This section can be replaced with this for loop, it's dynamic so it will work with any number for column in the csv file.

&nbsp;&nbsp;&nbsp;{% for element in range(list | count) %}  
&nbsp;&nbsp;&nbsp;{{ title[element] }}: {{ list[element] | trim }}  
&nbsp;&nbsp;&nbsp;{% endfor %}

---

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [December 3, 2017, 2:45pm UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/12 "2017-12-03T14:45:21Z")

</div>

Thanks Kai Stian, that is exactly what I was looking for.

---

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [December 8, 2017, 1:34am UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/13 "2017-12-08T01:34:21Z")

</div>

Kai Stian, I hope you can help with one more question. I searched but could not find out how to insert an ansible variable into the django loop.

---

<div class="post-metadata">

**Author:** ![Adolphson](https://avatars.discourse-cdn.com/v4/letter/a/e274bd/32.png) [@Adolphson](https://forum.ansible.com/u/Adolphson)\
**Post date:** [December 8, 2017, 1:42am UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/14 "2017-12-08T01:42:11Z")

</div>

I found out how. I created a variable for the {{ inventory\_hostname }} first.

vars:  
vsrx: “{{ inventory\_hostname }}”

{% set title = csvfile.split(“\n”)[0].split(‘,’) %}  
{% for item in csvfile.split(“\n”)[1:] %}  
**{% if vsrx in item %}**  
{% set list = item.split(“,”) %}  
{% for element in range(list | count) %}  
{{ title[element]|trim }}: {{ list[element]|trim }}  
{% endfor %}  
{% endif %}  
{% endfor %}

---

<div class="post-metadata">

**Author:** ![Kai\_Stian\_Olstad](https://avatars.discourse-cdn.com/v4/letter/k/e19adc/32.png) [@Kai\_Stian\_Olstad](https://forum.ansible.com/u/Kai_Stian_Olstad)\
**Post date:** [December 8, 2017, 7:57am UTC](https://forum.ansible.com/t/ansible-for-loop-on-csv-file-break-out-title-line/26165/15 "2017-12-08T07:57:06Z")

</div>

You don't need to do that, just use inventory\_hostname directly, it's already a variable.

{% if inventory\_hostname in item %}
