Ansible Regex_Findall Multiple Strings

Ansible regex_findall multiple sets

I was able to use with_list instead of with_items or with_nested. Works fine now with list of lists. Referenced my other post: Ansible list of lists - flattening

variable within regex_findall in ansible

I tried the following method, it works fine.

- name: Get names for all running Oracle databases from oratab file
slurp:
src: /etc/oratab
register: oracle_patch_oratab

- name: "assign pattern"
set_fact:
ora_ver: "12201"

- name: Extract a list of DBs which mataches the Oracle Home
set_fact:
oracle_patch_dblist: "{{ oracle_patch_oratab['content'] | b64decode | regex_findall ('(.+' + ora_ver | string + '.+)', multiline=True, ignorecase=True) }}"

Ansible or Python, how to use regex_findall on a list to return words that start with a certain pattern

edit: updated with the new requirement

While Frenchy's answer isn't wrong, it will be inherently slower and is a lot more verbose than the way Jinja2 wants that done which is via the |select filter, designed for working with list items:

- set_fact:
start_with_water: >-
{{ list1 | select('match', '^water')
| map('regex_findall', '([^ ]+) .*')
| map('first')
| list }}

produces

{
"ansible_facts": {
"start_with_water": [
"water_3gallons_6/20/22",
"water_1gal_today"
]
},
"changed": false
}

In case you were curious why your approach with regex_findall did not do what you expected, it's because that filter wants a string input, so jinja2 helpfully(?) coerced the list[str] into str by calling str(list1) and fed that into the filter which didn't match any "start of line" like you expected

Split a text to words with regex_findall

Map regex_findall, e.g.

    - debug:
msg: "{{ lookup('file', 'mycongig.txt').splitlines()|
map('regex_findall', '[\\w\\.]+')|
list }}"

gives

  msg:
- - key1
- 192.168.0.1
- - key2
- 192.168.0.2
- - key3
- 192.168.0.3
- - key4
- 192.168.0.4

How to use regex_findall in Ansible playbook properly?

It's helpful if you give a reproducible example. Here's one:

- hosts: localhost
connection: local
vars:
xyz: "hello"
tasks:
- debug:
msg: "{{ xyz | regex_findall('\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b') }}"
- debug: msg="done."

With -vvv, I get a more descriptive error message:

exception type: <class 'yaml.scanner.ScannerError'>
exception: while scanning a double-quoted scalar
in "<unicode string>", line 7, column 12:
msg: "{{ xyz | regex_findall('\b(?:[0 ...
^
found unknown escape character '.'
in "<unicode string>", line 7, column 53:
... regex_findall('\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b') }}"

So my first guess seems to have fixed it- double-backslash the backslashes.

- hosts: localhost
connection: local
vars:
# xyz: "hello"
xyz: "1.2.3.4"
tasks:
- debug:
msg: "{{ xyz | regex_findall('\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b') }}"
- debug: msg="done."

Ansible: What is the correct syntax for a variable within a findall regex

You never nest Jinja {{...}} template markers. Within a Jinja template, if you want to combine a literal string and a variable, you can use the ~ string concatenation operator, like this:

    - debug: msg="{{ nodeId.content | regex_findall("(\w+-\w+-\w+-\w+-\w+)..<address>\d+\.\d+\.\d+\.\d+:?\d+?<\/address><name>" ~ the_name) }}"

The ~ operator is like +, except it will convert arguments into
strings so that you can concatenate numeric values to a string
(writing "this " + 1 would fail, but "this " ~ 1 would work).

Or you can use Python string formatting syntax, like this:

    - debug: msg="{{ nodeId.content | regex_findall("(\w+-\w+-\w+-\w+-\w+)..<address>\d+\.\d+\.\d+\.\d+:?\d+?<\/address><name>%s" % (the_name)) }}"

This syntax uses printf-style formatting tokens (%s for strings,
%d for integers, etc). Or like this:

    - debug: msg="{{ nodeId.content | regex_findall("(\w+-\w+-\w+-\w+-\w+)..<address>\d+\.\d+\.\d+\.\d+:?\d+?<\/address><name>{}".format(the_name)) }}"

Here is one site that documents Python
string formatting in some detail.

Ansible regex_findall is not giving expected results with negative search

It's because that json_query emits a list[str] which when fed directly into regex_findall doesn't become a newline delimited string, it becomes the same as str(["alpha", "beta"]) (e.g. ['alpha', 'beta']) and then the multiline regex fails to do what you are expecting

There are, as with many things in life, a few ways to fix that. One is to just feed the results into |join("\n") and then you're likely back where you thought you were to begin with:

- debug:
msg: "{{ jsonOutput | json_query('json.response.results[].dnsName') | join('\n') | regex_findall('(?![a-z]{3}[0-9]{2}v)^.*', multiline=true) }}"

The other is to acknowledge that it's a list[str] and use the | select("match", ...) filter to only allow though items that match:

    - debug:
msg: >-
{{ response | json_query('results[].dnsName')
| select('match', '(?![a-z]{3}[0-9]{2}v)^.*')
| list }}
vars:
response:
results:
- dnsName: abc02vsomeserver01.subdomain1.domain.gov
- dnsName: abc02someserver01.subdomain1.domain.gov
- dnsName: xyz03votherserver11.subdomain2.domain.gov
- dnsName: wyz03otherserver11.subdomain2.domain.gov
- dnsName: qrsmainserver02.maindomain.domain.gov

similarly produces:

    "msg": [
"abc02someserver01.subdomain1.domain.gov",
"wyz03otherserver11.subdomain2.domain.gov",
"qrsmainserver02.maindomain.domain.gov"
]

I would guess it's personal preference which style works best in your playbook



Related Topics



Leave a reply



Submit