从输出中提取特定值

时间:2013-03-01 17:53:37

标签: tcl

我有一个pagent路由器输出

set pagent_ouput "Interface:    Ethernet2/3

packetfilter:   2500 123bps 456.123pps
packetfilter:   2300 345bps 345.548pps

Interface:    Ethernet3/4

packetfilter:   2500 123bps 896.163pps
packetfilter:   2300 345bps 675.748pps"

以太网接口各不相同....我想为每个以太网接口提取pps值 我想要类似的东西 { {456.123 345.548} {896.163 675.748}}

如果pagent_output变化为

set pagent_output "Interface:    Ethernet2/3

packetfilter:   2500 123bps 456.123pps
packetfilter:   2300 345bps 345.548pps
packetfilter:   2300 645bps 445.548pps
packetfilter:   2300 745bps 545.548pps

Interface:    Ethernet3/4

packetfilter:   2500 123bps 656.123pps
packetfilter:   2300 345bps 745.548pps
packetfilter:   2300 345bps 845.548pps
packetfilter:   2300 345bps 945.548pps

Interface:    Ethernet3/5

packetfilter:   2500 123bps 156.123pps
packetfilter:   2300 345bps 255.548pps
packetfilter:   2300 345bps 375.548pps
packetfilter:   2300 345bps 395.548pps"

the list will be { {456.123 345.548 445.548 545.548} {656.123 745.548 845.548 945.548} 
{156.123 255.548 375.548 395.548}}

2 个答案:

答案 0 :(得分:1)

首先,您需要将文本拆分为Interface行的片段,然后您想从这些片段中提取数据。 (以这种方式分解问题更容易,即使有其他方法可以做到这一点,因为在连接较小的问题而不是一个大问题方面考虑更大的问题更容易。)我们将使用常规用于提取的表达式;要跟随Tcl精确的RE方言,请务必查看relevant manual page

要将数据拆分为每个界面的部分,我建议使用textutil::split::splitx中的Tcllib命令。

package require textutil::split

set interface_data [textutil::split::splitx $pagent_output {(?n)^Interface:.*$}]

然后,我们希望从每个接口的数据中获取pps值;使用-all -inline选项的regexp是最佳工具:

set result {}
foreach item [lrange $interface_data 1 end] {
    lappend result [regexp -all -inline {\m[0-9.]+(?=pps)} $item]
}

现在,result变量保留了您的目标。


如果您已升级到Tcl 8.6,则可以通过使用lmap来缩短时间:

package require textutil::split

set result [lmap item [lrange [textutil::split::splitx $pagent_output {(?n)^Interface:.*$}] 1 end] {
    regexp -all -inline {\m[0-9.]+(?=pps)} $item
}]

但它仍然是基本的想法; textutil::split::splitx将事情分开(因为手动执行操作有点拖累)并在循环中regexp -all -inline来提取信息。

答案 1 :(得分:0)

我已经从cisco路由器做了一点提取输出以进行接口输出。 不确定这有什么帮助。

tcl regexp命令是我认为最好的选择。我不是tcl的专家,但是使用正则表达式,你可以匹配括号中你想要的任何内容。

set output "
packetfilter:   2500 123bps 456.123pps
packetfilter:   2300 345bps 345.548pps
packetfilter:   2300 645bps 445.548pps
packetfilter:   2300 745bps 545.548pps"

foreach line [split $output "\n"] {
set findpps [regexp {bps\s([0-9]+)\.([0-9]+)pps} $line fullmatch sub1 sub2]
if {$findpps == 1} {
puts "Int Eth2/3 PPS output is $sub1.$sub2"
}
}

将输出拆分为行 如果找到正则表达式,它将= 1。 sub1是“123bps”之后的第一个数字,sub2是第二个数字

在cisco land中,如果你想要所有接口的值,你可以编写一个脚本,通过“exec命令”获取所有接口输出,并以这种方式解析所有数据。