Here is an example:
- hosts: localhost
gather_facts: false
vars:
q: - ‘abc’
- 123
tasks: - debug:
msg: >-
{{ q is search(‘abc\t’) }}
This returns false. I have tried different variations of the regex, but nothing worked. Is this possible to do?
Here is an example:
This returns false. I have tried different variations of the regex, but nothing worked. Is this possible to do?
Escape the tab with another single quote, like this:
{{ q is search('abc\\t') }}
Dick
On 2022-06-20 (Mon) 13:52, Dick Visser w
Escape the tab with another single quote, like this:
I meant with another backslash obviously
q:
- 'abc<tab character here>'
- 123- debug:
msg: >-
{{ q is search('abc\t') }}
There are more aspects to this question:
* It's necessary to understand the difference between 'Double-Quoted
Style' and 'Single-Quoted Style'. See
https://yaml.org/spec/1.2.2/#731-double-quoted-style
https://yaml.org/spec/1.2.2/#732-single-quoted-style
In 'Single-Quoted Style' only "'" has to be escaped. As a result, the
string 'abc\t' doesn't include TAB. It's a sequence of characters: a,
b, c, \, t. Test it. The task below
- copy:
dest: /tmp/test.txt
content: |
{{ ql.0 }}
{{ ql.1 }}
vars:
ql:
- 'abc\tx'
- 123
gives
> cat /tmp/test.txt
abc\tx
123
The string will include TAB if you use 'Double-Quoted Style'
- copy:
dest: /tmp/test.txt
content: |
{{ ql.0 }}
{{ ql.1 }}
vars:
ql:
- "abc\tx"
- 123
gives
> cat /tmp/test.txt
abc x
123
* The *search* test doesn't work with lists. It works with strings.
See
https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html#testing-strings
Use it to test a single item of a list. For example,
- debug:
msg: "{{ ql.0 is search(regex) }}"
vars:
regex: 'abc\tx'
ql:
- "abc\tx"
- 123
gives
msg: true
Also the task below, with single-quoted *item* and escaped backslash
in *regex*, gives the same result
- debug:
msg: "{{ ql.0 is search(regex) }}"
vars:
regex: 'abc\\tx'
ql:
- 'abc\tx'
- 123
* Instead, you can "Test if a list contains a value". See
https://docs.ansible.com/ansible/latest/user_guide/playbooks_tests.html#testing-if-a-list-contains-a-value
For example, both tasks below returns *True*
- debug:
msg: "{{ item in ql }}"
vars:
item: 'abc\tx'
ql:
- 'abc\tx'
- 123
- debug:
msg: "{{ item in ql }}"
vars:
item: "abc\tx"
ql:
- "abc\tx"
- 123
* If you want to use *regex* to test an item in a list use *select*.
For example,
- debug:
msg: "{{ ql|select('search', regex) }}"
vars:
regex: 'abc\\tx'
ql:
- 'abc\tx'
- 123
gives
msg:
- abc\tx
, or use it in a condition. For example,
- debug:
msg: "Regex {{ regex }} is present in the list."
when: ql|select('search', regex)|length > 0
vars:
regex: 'abc\\tx'
ql:
- 'abc\tx'
- 123
gives
msg: Regex abc\\tx is present in the list.
Thank you for your replies. The search test does work with lists and this is where the
issue lies. Your examples helped me clear this up. The search, regex, etc tests will
convert the object to a string. In python code, this means that the list will be turned
into a string with str(list_here). This will escape tab characters in the list items, so
that a list [“a”, “b\t”] will get converted to the string, ‘[“a”, “b\t”]’. To match this correctly
with the search test, I need to search for …b\t… in single quotes.
There is also the case that the search test appears in an assert:
The tab character needs to be double escaped here because (I think)
the assert clause is interpreted as a double quoted string.
Correction:
assert:
that:
q is search(‘abc\t’ | regex_escape)
using regex_escape to avoid escaping manually the backslashes (‘abc\\t’)
I see. You're right. It's worth to test the escaping. The simplest
case is when the items are double-quoted and *regex* is variable
- debug:
msg: "{{ _list is search(regex) }}"
vars:
_list: ["a", "b\t"]
regex: 'b\\t'
Additional escaping, because of the outside double-quotes, is needed
when *regex* is value
- debug:
msg: "{{ _list is search('b\\\\t') }}"
vars:
_list: ["a", "b\t"]
Additional escaping is also needed when the items are single-quoted
and *regex* is variable. This time because of '\\' is needed after
evaluation
- debug:
msg: "{{ _list is search(regex) }}"
vars:
_list: ['a', 'b\t']
regex: 'b\\\\t'
Finally, one more additional escaping is needed when you put the
*regex* as a value
- debug:
msg: "{{ _list is search('b\\\\\\\\t') }}"
vars:
_list: ['a', 'b\t']
All tasks above return True.
This overview is worthy of its own paragraph in the ansible docs!