Ansible:如何使用正则表达式测试/筛选列表中的项目



在一个可靠的剧本中,我想在一个列表中的一组用户名上循环一个任务,前提是用户名或用户名后面跟着后缀'。A出现在另一个列表中。

失败的示例剧本:

---
- 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"

此版本跳过alice.A,而任务本身中的regex_replace筛选器按预期返回alice

实际输出:

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)

期望输出:

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)

是否可以对要测试的项目应用过滤器?如果没有,则有一种方法可以使用类似map()的东西来复制users2列表中附加"的条目。每个项目的后缀?

当我尝试过的条件都失败了:

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)"

最后一个只是检查测试项目是否被过滤器修改。(它不是AFAICT。(

不需要Regex。使用splitext获取真实名称并测试其在用户列表2中的存在
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when: realname in users2
vars:
realname: "{{ item|splitext|first }}"

给出预期结果

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)

你说你是

仅当用户名或用户名后面跟着后缀'时,才希望在一个列表中的一组用户名上循环任务。

上面的任务将接受任何后缀,而不仅仅是'。A’。还测试后缀以修复它。下面的任务给出了相同的结果

- 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) }}"

请参见提供默认值。


如果要使用正则表达式,请更改以下变量。这将得到相同的结果。

- 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'

更新

可选地,首先创建结构并简化任务中的代码

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 }}"

给出

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}

然后,下面的任务给出相同的结果

- 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') }}"

测试的完整剧本示例

- 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') }}"

最新更新