如何在 jinja2 中 select 正则表达式匹配?
how to select regex matches in jinja2?
玩具示例
基本上,我想做类似的事情:
['hello', 'apple', 'rare', 'trim', 'three'] | select(match('.*a[rp].*'))
这会产生:
['apple', 'rare']
我在说什么?
match
filter and select
过滤器。我的问题源于 select 过滤器仅支持一元 "tests".
我在使用 Ansible 1。9.x。
我的实际用例
...更接近于:
lookup('dig', ip_address, qtype="PTR", wantList=True) | select(match("mx\..*\.example\.com"))
所以,我想获取与某个 IP 关联的所有 PTR 记录,然后过滤掉所有不符合给定正则表达式的记录。我还想确保结果列表中只有一个元素,并输出该元素,但这是一个不同的问题。
这样行吗?
---
- hosts: localhost
connection: local
vars:
my_list: ['hello', 'apple', 'rare', 'trim', 'three']
my_pattern: '.*a[rp].*'
tasks:
- set_fact: matches="{{ my_list | map('regex_search',my_pattern) | select('string') | list }}"
failed_when: matches | count > 1
- debug: msg="I'm the only one - {{ matches[0] }}"
更新:它是如何工作的...
map 应用 过滤器 – 过滤器不是 yes/no 东西,它们应用于
输入列表的每个项目和修改项目的 return 列表。我用
regex_search
过滤器,每个项目的搜索模式 return
如果找到匹配项或 None 如果没有匹配项。所以在这一步我得到
此列表:[null, "apple", "rare", null, null]
.
然后我们使用select,它应用测试——测试是yes/no的东西,所以
他们根据选定的测试减少列表。我使用 string
测试,这是
当列表项为字符串时为真。所以我们得到:["apple", "rare"]
.
map
和 select
给了我们一些内部 python 类型,所以我们转换为列表
毕竟应用 list
过滤器。
这个设计模式对我有用:
----
- hosts: localhost
connection: local
vars:
my_list: ['hello', 'apple', 'rare', 'trim', "apropos", 'three']
my_pattern: 'a[rp].*'
tasks:
- set_fact:
matches: "{%- set tmp = [] -%}
{%- for elem in my_list | map('match', my_pattern) | list -%}
{%- if elem -%}
{{ tmp.append(my_list[loop.index - 1]) }}
{%- endif -%}
{%- endfor -%}
{{ tmp }}"
- debug:
var: matches
failed_when: "(matches | length) > 1"
如果你想在 Ansible 中过滤列表(获取具有空值的列表并与空列表进行区分),我发现了以下技巧:
---
- hosts: localhost
connection: local
vars:
regexp: '.*a[rp].*'
empty: [null]
tasks:
- set_fact: matches="{{ ['hello', 'apple', 'rare', 'trim', 'three'] | map('regex_search',regexp) | list|difference(empty) }}"
- debug: msg="{{ matches }}"
这是输出:
ok: [localhost] => {
"msg": [
"apple",
"rare"
]
}
您可以这样使用 select:
['hello', 'apple', 'rare', 'trim', 'three'] | select('match', '.*a[rp]')
这会产生:
['apple', 'rare']
match uses the re.match 实现,因此匹配字符串的开头。因此你需要 .*
在开头,而不是在正则表达式的结尾。
或者您可以使用 search
来完全避免 .*
:
['hello', 'apple', 'rare', 'trim', 'three'] | select('search', 'a[rp]')
玩具示例
基本上,我想做类似的事情:
['hello', 'apple', 'rare', 'trim', 'three'] | select(match('.*a[rp].*'))
这会产生:
['apple', 'rare']
我在说什么?
match
filter and select
过滤器。我的问题源于 select 过滤器仅支持一元 "tests".
我在使用 Ansible 1。9.x。
我的实际用例
...更接近于:
lookup('dig', ip_address, qtype="PTR", wantList=True) | select(match("mx\..*\.example\.com"))
所以,我想获取与某个 IP 关联的所有 PTR 记录,然后过滤掉所有不符合给定正则表达式的记录。我还想确保结果列表中只有一个元素,并输出该元素,但这是一个不同的问题。
这样行吗?
---
- hosts: localhost
connection: local
vars:
my_list: ['hello', 'apple', 'rare', 'trim', 'three']
my_pattern: '.*a[rp].*'
tasks:
- set_fact: matches="{{ my_list | map('regex_search',my_pattern) | select('string') | list }}"
failed_when: matches | count > 1
- debug: msg="I'm the only one - {{ matches[0] }}"
更新:它是如何工作的...
map 应用 过滤器 – 过滤器不是 yes/no 东西,它们应用于 输入列表的每个项目和修改项目的 return 列表。我用
regex_search
过滤器,每个项目的搜索模式 return 如果找到匹配项或 None 如果没有匹配项。所以在这一步我得到 此列表:[null, "apple", "rare", null, null]
.然后我们使用select,它应用测试——测试是yes/no的东西,所以 他们根据选定的测试减少列表。我使用
string
测试,这是 当列表项为字符串时为真。所以我们得到:["apple", "rare"]
.map
和select
给了我们一些内部 python 类型,所以我们转换为列表 毕竟应用list
过滤器。
这个设计模式对我有用:
----
- hosts: localhost
connection: local
vars:
my_list: ['hello', 'apple', 'rare', 'trim', "apropos", 'three']
my_pattern: 'a[rp].*'
tasks:
- set_fact:
matches: "{%- set tmp = [] -%}
{%- for elem in my_list | map('match', my_pattern) | list -%}
{%- if elem -%}
{{ tmp.append(my_list[loop.index - 1]) }}
{%- endif -%}
{%- endfor -%}
{{ tmp }}"
- debug:
var: matches
failed_when: "(matches | length) > 1"
如果你想在 Ansible 中过滤列表(获取具有空值的列表并与空列表进行区分),我发现了以下技巧:
---
- hosts: localhost
connection: local
vars:
regexp: '.*a[rp].*'
empty: [null]
tasks:
- set_fact: matches="{{ ['hello', 'apple', 'rare', 'trim', 'three'] | map('regex_search',regexp) | list|difference(empty) }}"
- debug: msg="{{ matches }}"
这是输出:
ok: [localhost] => {
"msg": [
"apple",
"rare"
]
}
您可以这样使用 select:
['hello', 'apple', 'rare', 'trim', 'three'] | select('match', '.*a[rp]')
这会产生:
['apple', 'rare']
match uses the re.match 实现,因此匹配字符串的开头。因此你需要 .*
在开头,而不是在正则表达式的结尾。
或者您可以使用 search
来完全避免 .*
:
['hello', 'apple', 'rare', 'trim', 'three'] | select('search', 'a[rp]')