如何在Ansible中使用字符串变量过滤列表?
Ansible列表过滤:结合正则与变量实现子串匹配
需求说明
给定列表:
list1: [ "aXYZb", "bbbb", "ccccXYZdsasd" ]
需过滤出包含目标子串(如XYZ)的元素,最终期望结果:
aXYZb ccccXYZdsasd
实际场景中,变量var1值为abcdef,列表元素格式为abcXYZdef,需结合提取子串的正则表达式完成过滤。
常见错误尝试
union过滤器:仅支持精确匹配元素,无法处理子串包含的场景。- 错误正则用法:
写法一(循环中错误调用全局列表的regex_search):
写法二(- name: Filter a list with variable set_fact: list2: "{{ list1 | regex_search('variable1') }}" loop: "{{ list1 }}" loop_control: loop_var: item5map+regex_search仅提取匹配内容,未保留原元素):list2: "{{ list1 | map('regex_search', some_regular_expression_with_variable) | list }}"
解决方案
方案1:直接匹配子串(简单场景)
若只需过滤包含指定子串的元素,使用select('contains', 目标变量)即可,无需正则:
- name: Filter elements containing target substring set_fact: filtered_list: "{{ list1 | select('contains', target_substring) | list }}" vars: target_substring: "XYZ"
执行后filtered_list将包含所有含XYZ的元素。
方案2:结合正则提取与变量匹配(复杂场景)
针对元素格式为abcXYZdef、变量var1=XYZ的场景,需先从元素中提取目标子串,再判断是否匹配变量,保留原元素:
方法A:循环收集符合条件的元素
- name: Initialize empty filtered list set_fact: filtered_list: [] - name: Collect elements where extracted content matches var1 set_fact: filtered_list: "{{ filtered_list + [item] }}" loop: "{{ list1 }}" when: item | regex_replace('(?:^.*(?=.{7})|\\d+)', '') == var1 vars: var1: "XYZ"
此方法遍历每个元素,用指定正则提取子串后与变量比较,符合条件则加入结果列表。
方法B:用select结合正则测试
通过select的match测试,直接匹配元素中符合正则模式的内容(需将变量转为正则安全格式):
- name: Filter elements using regex match with variable set_fact: filtered_list: "{{ list1 | select('match', '.*' ~ (var1 | regex_escape) ~ '.*') | list }}" vars: var1: "XYZ"
regex_escape用于转义变量中的特殊字符,避免正则语法冲突。
方案3:结合自定义正则提取逻辑
如果需要用regex_search提取子串后判断,可使用jinja2的表达式过滤:
filtered_list: "{{ list1 | select( item | regex_search('\\D(?=.{0,6}$)') == var1 ) | list }}"
此写法直接在select中判断元素提取后的内容是否等于变量,简洁高效。
内容的提问来源于stack exchange,提问作者LJS
相关产品推荐
相关产品推荐

