[英]Ansible: How do I test/filter items in a list using a regex?
In an ansible playbook I want to loop a task over a set of usernames from one list only if the username or username followed by a suffix '.A' occurs in another list.在 ansible 剧本中,我想仅当用户名或后跟后缀“.A”的用户名出现在另一个列表中时,才对一个列表中的一组用户名循环执行任务。
Sample playbook that fails:失败的示例剧本:
---
- hosts: localhost
vars:
- users1:
- alice
- alice.A
- bob
- santa
- users2:
- alice
tasks:
- debug:
msg: "Do something for {{ item }} realname {{ item | regex_replace('^([a-z]+)\\.[aA]$', '\\1') }}"
loop: "{{ users1 }}"
when:
- "item | regex_replace('^([a-z]+)\\.[aA]$', '\\1') in users2"
This version skips alice.A
while the regex_replace
filter in the task itself returns alice
as expected.此版本跳过alice.A
,而任务本身中的regex_replace
过滤器按预期返回alice
。
Actual output:实际 output:
TASK [debug] ***************
ok: [localhost] => (item=alice) => {}
MSG:
Do something for alice realname alice
skipping: [localhost] => (item=alice.A)
skipping: [localhost] => (item=bob)
skipping: [localhost] => (item=santa)
Desired output:所需的 output:
TASK [debug] ***************
ok: [localhost] => (item=alice) => {}
MSG:
Do something for alice realname alice
Do something for alice.A realname alice
skipping: [localhost] => (item=bob)
skipping: [localhost] => (item=santa)
Is it possible to apply a filter to the item to be tested?是否可以对要测试的项目应用过滤器? If not is there a way to use something like map()
to duplicate the entries in the users2
list appending the '.A' suffix to each item?如果没有,有没有办法使用map()
之类的东西来复制users2
列表中的条目,并在每个项目后附加“.A”后缀?
When conditions I have tried that all fail:当我尝试过的条件都失败时:
when: ("item in users2 | flatten(1)") or
("item|regex_search('\.A$')")
when:
- "item | regex_replace('^([a-z]+\\.[a-z]+).[aA]$', '\\1') in users | flatten(1)"
when:
- "item in users | flatten(1) | map('regex_replace','^([a-z]+\\.[a-z]+)$', '\\1.A')"
when:
- "item | map('regex_replace','^([a-z]+\\.[a-z]+).[aA]$', '\\1') in users | flatten(1)"
when:
- "item|map('upper') in users | flatten(1)"
The last one just to check whether the item tested was modified by the filter or not.最后一个只是检查测试的项目是否被过滤器修改。 (It is not AFAICT.) (这不是 AFAICT。)
Regex is not needed.不需要正则表达式。 Use splitext to get the realname and test its presence in the list users2使用splitext获取真实姓名并测试其在列表users2中的存在
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when: realname in users2
vars:
realname: "{{ item|splitext|first }}"
gives the expected results给出了预期的结果
TASK [debug] ********************************************************
ok: [localhost] => (item=alice) =>
msg: Do something for alice realname alice.
ok: [localhost] => (item=alice.A) =>
msg: Do something for alice.A realname alice.
skipping: [localhost] => (item=bob)
skipping: [localhost] => (item=santa)
You say you你说你
want to loop a task over a set of usernames from one list only if the username or username is followed by a suffix '.A'仅当用户名或用户名后跟后缀“.A”时,才希望对一个列表中的一组用户名循环执行任务
The task above will accept any suffix not only '.A'.上面的任务将接受任何后缀,而不仅仅是“.A”。 Test also the suffix to fix it.还测试后缀以修复它。 The task below gives the same result下面的任务给出了相同的结果
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when:
- realname in users2
- suffix == '.A'
vars:
arr: "{{ item|splitext|list }}"
realname: "{{ arr.0 }}"
suffix: "{{ arr.1|default('.A', true) }}"
See Providing default values .请参阅提供默认值。
If you want to use regex change the variables below.如果您想使用正则表达式,请更改以下变量。 This will give the same results.这将给出相同的结果。
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when: realname in users2
vars:
realname: "{{ item|regex_replace(regex, replace) }}"
regex: '^(.*?)(\.A)*$'
replace: '\1'
Update更新
Optionally, create the structure first and simplify the code in the tasks或者,先创建结构并简化任务中的代码
users3_str: |
{% for u in users1 %}
{% set arr = u|splitext|list %}
- name: {{ u }}
realname: {{ arr.0 }}
suffix: {{ arr.1|default('.A', true) }}
{% endfor %}
users3: "{{ users3_str|from_yaml }}"
gives给
users3:
- {name: alice, realname: alice, suffix: .A}
- {name: alice.A, realname: alice, suffix: .A}
- {name: bob, realname: bob, suffix: .A}
- {name: santa, realname: santa, suffix: .A}
Then, the tasks below give the same results然后,下面的任务给出相同的结果
- debug:
msg: "Do something for {{ item.name }} realname {{ item.realname }}."
loop: "{{ users3|selectattr('realname', 'in', users2) }}"
- debug:
msg: "Do something for {{ item.name }} realname {{ item.realname }}."
loop: "{{ users3|selectattr('realname', 'in', users2)|
selectattr('suffix', '==', '.A') }}"
Example of a complete playbook for testing用于测试的完整剧本示例
- hosts: localhost vars: users1: - alice - alice.A - bob - santa users2: - alice users3_str: | {% for u in users1 %} {% set arr = u|splitext|list %} - name: {{ u }} realname: {{ arr.0 }} suffix: {{ arr.1|default('.A', true) }} {% endfor %} users3: "{{ users3_str|from_yaml }}" tasks: - debug: var: users3|to_yaml - debug: msg: "Do something for {{ item.name }} realname {{ item.realname }}." loop: "{{ users3|selectattr('realname', 'in', users2) }}" - debug: msg: "Do something for {{ item.name }} realname {{ item.realname }}." loop: "{{ users3|selectattr('realname', 'in', users2)| selectattr('suffix', '==', '.A') }}"
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.