该项目位置 --> 链接

项目核心代码基于 TTP --> 链接


TTP _start__end_ 用法总结

基于实验验证,非文档推断。


_start_

核心规则

group 的第一行模板永远是触发行,不需要 _start_
_start_ 只有一个用途:把 group 里的非第一行也提升为触发行。

触发行的作用:命中时,保存当前记录,开启新记录。

什么时候不需要 _start_

group 里只有一种触发行格式,且它就是第一行:

<group name="vpn">
ip vpn-instance {{ name }}    ← 第一行,自动触发,无需 _start_
 rd {{ rd }}
</group>

输入多个 ip vpn-instance 块时,每次命中第一行都会自动保存上一条、开启新记录。

什么时候需要 _start_

group 里有多种格式的触发行,且不是第一行:

<group name="interfaces">
interface Tunnel{{ id }}                    ← 第一行,默认触发
interface GigabitEthernet{{ id | _start_ }} ← 非第一行,必须加 _start_
interface Loopback{{ id | _start_ }}        ← 非第一行,必须加 _start_
 description {{ desc }}
</group>

不加 _start_ 的后果:GigabitEthernetLoopback 接口完全丢失,只有 Tunnel 接口被捕获。

正确写法 vs 错误写法

写法

正则结果

变量捕获

触发效果

{{ id | _start_ }}

(?P<id>\S+)

✅ id 正常捕获

✅ 触发新记录

{{ id }}{{ _start_ }}

(?P<id>\S+)(?P<_start_>\S+)

❌ id 丢失

不稳定

{{ id }} {{ _start_ }}

(?P<id>\S+)\s+\S+

❌ 匹配失败

结论:永远用管道符写法 {{ varname | _start_ }},不要把 {{ _start_ }} 单独写在同一行其他变量旁边。

_start_ 与触发行无关数据的写法

触发行本身没有需要捕获的数据时,_start_ 单独写:

<group name="cdp">
{{ _start_ }}-------------------------   ← 分隔线,无数据,_start_ 单独写
Device ID: {{ device_id }}
  IP address: {{ ip }}
</group>

_end_

TTP 的自动边界检测

不加 _end_ 时,TTP 依赖两种机制自动保存记录:

  1. 新触发行到来:先保存当前记录,再开启新记录

  2. 顶格非触发行到来:自动保存当前记录,group 回到未激活状态

interface Gi0/1         ← 触发,开始收集
 ip address 10.0.0.1    ← 收集
router ospf 1           ← 顶格 + 非触发 → 自动保存 Gi0/1,group 停止收集
 ip address 172.16.0.1  ← group 未激活,忽略,不会污染 Gi0/1
interface Loopback0     ← 触发,开始收集新记录

什么时候不需要 _end_

对于典型的网络设备配置文件,绝大多数情况不需要 _end_

  • 每个配置块都以顶格行开始(interfacerouterip vpn-instance 等)

  • TTP 的自动边界检测能正确处理这类结构

  • 多次实验验证:有无 _end_ 结果完全相同

什么时候需要 _end_

配合 _line_ 使用时_end_ 是推荐写法。

_line_ 会匹配任意行,计算开销大。_end_ 让它提前停止扫描,减少不必要的匹配:

<group name="interfaces">
interface {{ interface }}
 {{ port_sec | _line_ | contains("port-security") | joinmatches }}
!{{ _end_ }}    ← 告诉 _line_:到 ! 就停,不要继续扫描后面的内容
</group>

这里 _end_ 的作用是性能优化,不是正确性保障。

多种结束条件

结束行有多种格式时,写多行 _end_,任意一行命中都触发保存:

<group name="interfaces">
interface {{ interface }}
 ip address {{ ip }} {{ mask }}
!{{ _end_ }}       ← IOS 风格
quit{{ _end_ }}    ← 华为风格
return{{ _end_ }}  ← 华为风格
</group>

对比总结

场景

_start_

_end_

group 第一行,同格式重复

不需要

不需要

group 非第一行,需要触发

必须加

不需要

配合 _line_ 使用

视情况

建议加(性能)

触发行之间有相同格式的干扰行

不需要

实验证明也不需要

纯分隔行作为触发(无变量)

{{ _start_ }} 单独写

多种结束条件

写多行 _end_


一句话判断

需要 _start_ 的判断: 这行是不是 group 的第一行?不是 → 加 _start_

需要 _end_ 的判断: 这个 group 里有没有用 _line_?有 → 加 _end_。其他情况 TTP 自动处理。

未完待续...