Ansible:如何使用正则表达式 test/filter 列表中的项目?
Ansible: How do I test/filter items in a list using a regex?
在 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
而任务本身 returns alice
中的 regex_replace
过滤器符合预期。
实际输出:
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
列表中的条目,并在每个项目后附加“.A”后缀?
当我尝试过的所有条件都失败时:
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。)
不需要正则表达式。使用 splitext 获取 realname 并测试其在列表 users2
中的存在
- 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)
你说你
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”。还测试后缀以修复它。下面的任务给出了相同的结果
- 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) }}"
如果您想使用 regex,请更改以下变量。这将给出相同的结果。
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when: realname in users2
vars:
realname: "{{ item|regex_replace(regex, replace) }}"
regex: '^(.*?)(\.A)*$'
replace: ''
在 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
而任务本身 returns alice
中的 regex_replace
过滤器符合预期。
实际输出:
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
列表中的条目,并在每个项目后附加“.A”后缀?
当我尝试过的所有条件都失败时:
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。)
不需要正则表达式。使用 splitext 获取 realname 并测试其在列表 users2
中的存在 - 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)
你说你
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”。还测试后缀以修复它。下面的任务给出了相同的结果
- 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) }}"
如果您想使用 regex,请更改以下变量。这将给出相同的结果。
- debug:
msg: "Do something for {{ item }} realname {{ realname }}."
loop: "{{ users1 }}"
when: realname in users2
vars:
realname: "{{ item|regex_replace(regex, replace) }}"
regex: '^(.*?)(\.A)*$'
replace: ''