Ansible中筛选URL不匹配指定正则的字典及正则简化匹配方法
问题
我有一个字典列表,示例如下:
[ { "url": "bucket.amazonaws.com", "file": "file1.txt" }, { "url": "github.com", "file": "file2.txt" } ]
目前可通过以下方式筛选存储在AWS中的文件:
aws_files: "{{ array | selectattr('url', 'match', '.*amazonaws\\.com.*') }}"
或是存储在GitHub中的文件:
github_files: "{{ array | selectattr('url', 'match', '.*github\\.com.*') }}"
现在需要筛选不匹配上述任一正则模式的所有文件,尝试了两种写法均无效:
remaining_files: "{{ not (array | selectattr('url', 'match', '.*(amazonaws|github)\\.com.*')) }}"
remaining_files: "{{ array | selectattr('url', 'notmatch', '.*(amazonaws|github)\\.com.*') }}"
另外还有一个次要问题:是否存在无需在正则模式首尾添加.*,即可在字符串任意位置匹配该模式的方法?
解决方案
1. 筛选不匹配规则的文件
你用反向匹配的思路是对的,但错误在于过滤器的用法:selectattr并不支持notmatch作为匹配类型,而用not包裹筛选结果只会得到布尔值,不是目标列表。
正确的做法是使用rejectattr过滤器——它和selectattr作用相反,会排除所有符合匹配条件的元素,留下不匹配的:
remaining_files: "{{ array | rejectattr('url', 'match', '.*(amazonaws|github)\\.com.*') }}"
2. 简化正则匹配(无需首尾.*)
Jinja2的match过滤器默认要求全字符串匹配,所以必须加.*才能匹配任意位置的子串。但如果改用search过滤器,它会直接在字符串的任意位置查找匹配的子串,不需要额外添加.*。
比如筛选AWS文件可以简化为:
aws_files: "{{ array | selectattr('url', 'search', 'amazonaws\\.com') }}"
对应的反向筛选写法为:
remaining_files: "{{ array | rejectattr('url', 'search', '(amazonaws|github)\\.com') }}"
内容的提问来源于stack exchange,提问作者jeremywat
相关产品推荐
相关产品推荐

