简体   繁体   English

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

[英]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.

相关问题 如何使用复选框过滤多个列表项? - How do I filter multiple list items using checkboxes? 如何通过ansible / jinja2中属性的存在来过滤列表? - How do I filter a list by existance of an attribute in ansible/jinja2? 如何针对以下内容使用“匹配正则表达式”过滤cpanel中的电子邮件? - How do I filter email in cpanel using 'match regex' for the following? 如何过滤 Clojure 中的向量列表? - How do I filter a list of vectors in Clojure? 如果某些列表项出现在另一个列表中,如何使用 str.lower() 使它们小写? - How do I make certain list items lowercase using str.lower() if they appear on another list? 迭代过滤器:如何过滤多个元组的列表? - Iterating filter: How do I filter a list for multiple tuples? 使用熊猫,如何将一个 csv 文件列转换为列表,然后使用创建的列表过滤不同的 csv? - Using pandas, how do I turn one csv file column into list and then filter a different csv with the created list? 如何使用Odata从嵌套在列表中的动态数据中进行过滤? - How do I filter using Odata from dynamic data nested in a list? 使用BCS筛选器限制外部列表上的项目 - Limit items on external list using BCS Filter 使用regex.pattern过滤列表 - Filter a list using regex.pattern
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM