我正在尝试使用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。
我该怎么做才能解决这个问题?我认为这可能是我的正则表达式字符串的一个问题,它从每行抓取第一个单词。
答案 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;无论如何都是好风格。)