为什么我的TCL表达式返回重复的结果

时间:2017-06-23 18:36:22

标签: regex scripting tcl

我正在尝试使用TCL来处理cisco路由器上的所有接口。目前我正在使用以下两个命令:

set int_out [exec "show interface description"]

输出

Interface                      Status         Protocol Description
Fa0/0                          up             up       ** REDACTED **
Fa0/0.209                      up             up       ** REDACTED **
Fa0/0.790                      up             up       ** REDACTED **
Fa0/1                          admin down     down

foreach int [regexp -all -line -inline "^(\[^ ]+)" $int_out] { show clock; puts $int }

输出

18:25:16.461 UTC Fri Jun 23 2017Interface

18:25:16.465 UTC Fri Jun 23 2017Interface

18:25:16.469 UTC Fri Jun 23 2017Fa0/0

18:25:16.469 UTC Fri Jun 23 2017Fa0/0

18:25:16.473 UTC Fri Jun 23 2017Fa0/0.209

18:25:16.473 UTC Fri Jun 23 2017Fa0/0.209

18:25:16.477 UTC Fri Jun 23 2017Fa0/0.790

18:25:16.477 UTC Fri Jun 23 2017Fa0/0.790

18:25:16.481 UTC Fri Jun 23 2017Fa0/1

18:25:16.481 UTC Fri Jun 23 2017Fa0/1

我的目标是从显示界面描述的每行输出中获取接口名称,然后在屏幕上将其打印出来。但正如您所看到的,当我在屏幕上打印数据时,我会得到重复的内容。我认为这可能是由于某种屏幕上的日志记录功能,但我输出中包含的时间戳似乎表明不是这样。例如,第一个接口行的时间戳为18:25:16.461,而第二个接口行的时间戳为18:25:16.465。

我该怎么做才能解决这个问题?我认为这可能是我的正则表达式字符串的一个问题,它从每行抓取第一个单词。

1 个答案:

答案 0 :(得分:2)

问题在于regexp -inline为每个子匹配的整体匹配返回一个单词。在这里,我们来看一个简单的例子:

puts [regexp -all -inline {.(.).} "abcdef"]

这会产生此输出:

abc b def e

当您创建匹配字符串的所有非空部分的子RE时,就像在^([^ ]+)中一样,您将获得整个匹配的字符串,显然会返回两次。

您可能的修复方法是更改​​RE,以便它不会使用捕获括号(在您的情况下,您可以使用^[^ ]+,并且需要使用任何反斜杠来完成它Tcl解析器),或使用foreach的多变量形式,以便您处理(忽略?)您不关心的所有匹配的子部分:

foreach {int inner} [regexp -all -line -inline "^(\[^ ]+)" $int_out] {
    show clock
    puts $int
}

(FWIW,您通常建议将RE放在{大括号}中,以避免添加大量反斜杠。这不是您的问题,但它& #39;无论如何都是好风格。)