Ansible/Python如何用regex_findall提取列表指定前缀开头的内容
问题根因
之前的写法返回空列表、拿不到预期结果,核心是两个用法错误:
regex_findall过滤器的输入参数必须是字符串,直接传入列表时不会自动遍历每个列表元素做匹配,只会对列表的整体序列化结果做正则匹配,自然找不到目标内容- 所用的正则
^water/\Awater仅能匹配开头的water这5个字符,既不会提取water后面跟随的前缀内容,也不会裁剪掉条目末尾的空格+数字编号段,完全不符合提取需求
可用实现方案
以下两种写法都可以直接拿到你预期的结果列表['water_3gallons_6/20/22','water_1gal_today']:
方案1:筛选+裁剪组合写法(可读性最好)
通过select筛选符合前缀要求的条目,再通过正则替换裁掉末尾的无用编号段,逻辑清晰好维护:
- name: 提取所有以water开头的内容前缀 set_fact: start_with_water: "{{ list1 | select('search', '^water') | map('regex_replace', '\\s+\\d+$', '') | list }}"
各段过滤器作用:
select('search', '^water'):遍历列表所有元素,保留以water开头的条目,过滤掉其余不相关内容map('regex_replace', '\\s+\\d+$', ''):对筛选出的每个条目,将末尾连续空格+行尾数字的部分替换为空,正好裁掉后面的4908xx编号list:将迭代器转换为标准Ansible列表格式
方案2:纯regex_findall写法
如果要坚持用regex_findall实现,必须先通过map遍历列表元素,同时写对匹配规则,自动在第一个空格处截断:
- name: 通过regex_findall提取目标内容 set_fact: start_with_water: "{{ list1 | map('regex_findall', '^water\\S+') | flatten | list }}"
这里正则^water\\S+的匹配逻辑是:从行首开始匹配water,之后连续匹配所有非空白字符,遇到第一个空格就停止,正好自动排除后面的编号段;最后用flatten把每个元素匹配生成的子列表拍平为一维普通列表即可。
避坑说明
- Ansible的字符串处理过滤器默认不会自动遍历列表,处理列表元素必须配合
map/select这类迭代类过滤器使用 - 写正则时要明确匹配范围,只写开头关键词只能拿到关键词本身,拿不到完整的目标片段
- 如果要匹配行首/字符串开头,在
search/match测试里直接用^即可,不需要额外转义
内容的提问来源于stack exchange,提问作者NewbChewbCS
相关产品推荐
相关产品推荐

