You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Ansible Jinja2正则无法匹配字符串开头问题排查

环境信息

我使用的环境如下:

ansible 2.9.27
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /bin/ansible
  python version = 2.7.5 (default, May 27 2022, 11:27:32) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]
需求与问题

我需要从名为found_routes的列表中移除以"default"开头的元素,生成新列表,但正则匹配字符串开头的操作出现异常。

我的列表内容:

[ u'default via 10.13.99.1 dev bond0.99',
  u'10.13.101.0/23 dev p1p1.101',
  u'128.1.66.227 via 10.13.201.1 dev p1p1.201' ]
尝试操作

我先尝试用以下代码过滤:

- name: Populate appended route list
  set_fact:
    found_added_routes: "{{ found_routes | select('search', ' via ') | reject('regex', '^default') | list }}"

这段代码无法过滤掉第一个默认路由条目,但改用下面的代码就能生效:

- name: Populate appended route list
  set_fact:
    found_added_routes: "{{ found_routes | select('search', ' via ') | reject('regex', '^..default') | list }}"

我想知道:字符串开头存在哪两个不可见字符,导致必须用^..default才能匹配?

调试输出

我的调试代码:

- name: Debug found_routes
  debug:
    msg: "Found route list: {{ item }}"
  loop: "{{ found_routes }}"

- name: Debug found_added_routes
  debug:
    msg: "Found: {{ item }}"
  loop: "{{ found_added_routes }}"

成功过滤后的调试输出:

TASK [networks : Debug found_route_list] **********************************************************************************************************************
ok: [server01.example.com] => (item=default via 10.13.99.1 dev bond0.99) => {
    "msg": "Found route list: default via 10.13.99.1 dev bond0.99"
}
ok: [server01.example.com] => (item=10.13.101.0/24 dev p1p1.101) => {
    "msg": "Found route list: 10.13.101.0/24 dev p1p1.101"
}
ok: [server01.example.com] => (item=128.1.66.227 via 10.13.101.1 dev p1p1.101) => {
    "msg": "Found route list: 128.1.66.227 via 10.13.101.1 dev p1p1.101"
}

TASK [networks : Debug found_added_routes] **********************************************************************************************************************
ok: [server01.example.com] => (item=10.13.101.0/24 dev p1p1.101) => {
    "msg": "Found: 10.13.101.0/24 dev p1p1.101"
}
ok: [server01.example.com] => (item=128.1.66.227 via 10.13.101.1 dev p1p1.101) => {
    "msg": "Found: 128.1.66.227 via 10.13.101.1 dev p1p1.101"
}
问题分析与解决

你遇到的情况大概率是字符串开头存在UTF-8 BOM(字节顺序标记),也就是\xef\xbb\xbf这三个字节,在Python 2.7的字符串处理逻辑下,可能只体现出前两个字节的影响;另一种可能是从命令输出(比如ip route)获取路由信息时,输出包含了开头的空格、制表符这类不可见空白字符,只是调试输出没有显示出来。

要验证具体是什么字符,可以添加以下调试任务,把字符串转成Base64编码后输出,解码就能看到原始字节:

- name: Debug raw bytes of route items
  debug:
    msg: "{{ item | string | b64encode }}"
  loop: "{{ found_routes }}"

更稳妥的过滤方式,不需要依赖匹配前两个字符,直接用正则匹配任意开头空白后接"default"即可:

- name: Populate appended route list
  set_fact:
    found_added_routes: "{{ found_routes | select('search', ' via ') | reject('regex', '^\\s*default') | list }}"

这里\s*会匹配0个或多个空白字符(空格、制表符等),不管开头有没有不可见字符,都能正确过滤默认路由。

内容的提问来源于stack exchange,提问作者Mike S

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 06:10:49