繁体   English   中英

Ansible:如何使用正则表达式测试/过滤列表中的项目?

[英]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 ,而任务本身中的regex_replace过滤器按预期返回alice

实际 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)

所需的 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)

是否可以对要测试的项目应用过滤器? 如果没有,有没有办法使用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获取真实姓名并测试其在列表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)

你说你

仅当用户名或用户名后跟后缀“.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) }}"

请参阅提供默认值


如果您想使用正则表达式,请更改以下变量。 这将给出相同的结果。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM