# Set variable based on a file's string search

**URL:** <https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708>\
**Category:** Ansible Project\
**Created:** [March 7, 2024, 4:02pm UTC](https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708 "2024-03-07T16:02:18Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![Alex\_Wanderley](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/alex_wanderley/32/3232_2.png) [@Alex\_Wanderley](https://forum.ansible.com/u/Alex_Wanderley)\
**Post date:** [March 7, 2024, 4:02pm UTC](https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708/1 "2024-03-07T16:02:18Z")

</div>

Hello,

(And apologies if this is something too trivial…)

I have a working playbook that searches and collects a string from a file and, based on that string, sets another variable.  
But I’m retrieving the string using grep/awk:

- name: Collect server location  
ansible.builtin.shell: “/bin/grep {{ inventory\_hostname }} {{ server\_list\_file }} | /bin/awk ‘{print $3}’”  
register: grep\_result  
changed\_when: ( grep\_result.rc != 0 )

“{{ server\_list\_file }}” points to a file that looks like this:  
serverA flavor locationX owner  
serverB flavor locationY owner  
serverC flavor locationZ owner

For completeness, this is how I’m using “grep\_result”:

- name: Set snmpd config file  
ansible.builtin.set\_fact:  
snmpd\_conf: “{% if grep\_result.stdout == ‘locationX’ %}snmpd.conf-X  
{% elif grep\_result.stdout == ‘locationY’ %}snmpd.conf-Y  
{% else %}snmpd.conf-Z  
{% endif %}”

How could I, as simply as using the command/shell modules, accomplish the same results without resourcing to shell commands?

Thanks a lot,

Alex

---

<div class="post-metadata">

**Author:** ![utoddl](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/utoddl/32/249_2.png) [@utoddl](https://forum.ansible.com/u/utoddl)\
**Post date:** [March 7, 2024, 4:54pm UTC](https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708/2 "2024-03-07T16:54:37Z")

</div>

I’m curious how these notions caught on that very clearly expressed shell expressions are inherently “bad”, and that unfathomably complex jinja2 expressions are inherently “better”.

I seriously doubt you’re going to find a more maintainable, all-Ansible expression to accomplish what you’re doing.

However, I would suggest a couple alterations.  
(A) I’d make that “changed\_when:” into a “failed\_when:”, and  
(B) I’d add “changed\_when: false” (because it doesn’t ever change anything).  
(C) I might also add a “vars:” to your set\_fact task that maps “location[XYZ]” to your smtp.conf expressions:

```auto
  vars:
    locmap:
      locationX: snmpd.conf-X
      locationY: snmpd.conf-Y
      locationZ: snmpd.conf-Z

```

Then your set\_fact becomes "snmpd\_conf: ‘{{ locmap[grep\_result.stdout\_lines[0]] }}’  
That way you don’t have to change “code” to update your location map data.

---

<div class="post-metadata">

**Author:** ![Alex\_Wanderley](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/alex_wanderley/32/3232_2.png) [@Alex\_Wanderley](https://forum.ansible.com/u/Alex_Wanderley)\
**Post date:** [March 7, 2024, 5:42pm UTC](https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708/3 "2024-03-07T17:42:29Z")

</div>

Thanks a lot for the insights, Tod. Very appreciated…  
And suggestions as well. I’ll give them a try.

I’m still in an Ansible learning process and sometimes I also come upon that curiosity of yours…  
How come the notion of avoiding shell “at all cost” exists even for very specific situations, like this one.  
That’s why I, based on the “no shell” assumption, tried to make my playbook better.

Regards,

Alex

---

<div class="post-metadata">

**Author:** ![Will\_McDonald](https://avatars.discourse-cdn.com/v4/letter/w/f475e1/32.png) [@Will\_McDonald](https://forum.ansible.com/u/Will_McDonald)\
**Post date:** [March 7, 2024, 6:24pm UTC](https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708/4 "2024-03-07T18:24:44Z")

</div>

I suspect the broad notion that shell == bad and native statements == good is probably just conflation/extrapolation. And human nature 🙂

The generally received wisdom when I was taught Ansible by Ansible folk was native modules \> command \> shell.

Note this is not ‘no shell at any costs’, but rather, try and avoid shell because it can be fragile with globbing, expansion, unexpected behaviour with weird file names etc.

Second thought, on this topic is you could collapse the shell to command here like so:

- name: Collect server location command  
ansible.builtin.command: /bin/awk ‘/{{ inventory\_hostname }}/ { print $3 }’ {{ server\_list\_file}}  
register: command\_result  
changed\_when: ( command\_result.rc != 0 )

And finally, while the general pattern probably fits your purposes Alex, it kinda feels like getting stuff that might more naturally be considered inventory information from flat/static files? That’s probably totally cool for your current needs but I’d potentially think about exposing location as a fact, either through inference from dynamic inventory/inventory plugins, or baking into custom facts so the host can report its location (though you might have some chicken-and-egg constraints guiding you down your current path.)

---

<div class="post-metadata">

**Author:** ![Walter\_Rowe](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/walter_rowe/32/4506_2.png) [@Walter\_Rowe](https://forum.ansible.com/u/Walter_Rowe)\
**Post date:** [March 7, 2024, 6:27pm UTC](https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708/5 "2024-03-07T18:27:59Z")

</div>

- name: Collect server location  
ansible.builtin.shell: “/bin/awk ‘$1 ~ /{{ inventory\_hostname }}/ { print $3 }’ {{ server\_list\_file }}”

register: grep\_result  
changed\_when: ( grep\_result.rc != 0 )

You don’t need grep AND awk. Learn to use awk’s expressions to find what you need in a single command.

% cat serverlist.txt

serverA flavor locationX owner

serverB flavor locationY owner

serverC flavor locationZ owner

% awk ‘$1 ~ /serverB/ { print $3; }’ serverlist.txt

locationY

Walter

---

<div class="post-metadata">

**Author:** ![Alex\_Wanderley](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/alex_wanderley/32/3232_2.png) [@Alex\_Wanderley](https://forum.ansible.com/u/Alex_Wanderley)\
**Post date:** [March 7, 2024, 6:40pm UTC](https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708/6 "2024-03-07T18:40:46Z")

</div>

Hi Walter,

Yes, that’s how I usually go with (no grep + awk).  
But back then, I was having so many “trouble” escaping the special characters associated with awk’s syntax that I decided to go that way.  
Now that things are looking better, I’ll give that a try again. Otherwise I’ll miss learning…

Thanks,  
Alex

---

<div class="post-metadata">

**Author:** ![Alex\_Wanderley](https://sea1.discourse-cdn.com/ansible/user_avatar/forum.ansible.com/alex_wanderley/32/3232_2.png) [@Alex\_Wanderley](https://forum.ansible.com/u/Alex_Wanderley)\
**Post date:** [March 7, 2024, 6:56pm UTC](https://forum.ansible.com/t/set-variable-based-on-a-files-string-search/38708/7 "2024-03-07T18:56:37Z")

</div>

Thanks, Will  
Yes, I may have exaggerated a bit by going with ‘avoid at all cost’… 🙂 You are right about the modules \> command \> shell statement. But that still made me think the solution I used was not the way to go.

“(though you might have some chicken-and-egg constraints guiding you down your current path.)” Yup, that’s exactly the reason.  
For now I have to rely on collecting that information from an already established way of locating our servers.  
Eventually will migrate away from that and have something more coupled with Ansible. Thank you for your suggestions, by the way…

Regards,

Alex
