期望脚本:从Cisco CLI解析特定信息

问题描述 投票:0回答:3

我是Expect脚本新手,并尝试解析Cisco路由器ACL输出。

我特意尝试解析前2条备注行之间的IP地址。任何帮助非常感谢。


这是我随机尝试之一。它解析ACL中的IP地址,但不会停在第二条注释行:

send "show run | section ip access-list extended OUTSIDE\r\n"
set ip {}
    expect {
       "remark ##### DENIED HOSTS #####\r\n" {
          expect -re {(\d+\.\d+\.\d+\.\d+)} {
            set ip "${ip}$expect_out(0,string)"
            puts $ip
            set ip {}
            exp_continue
            }
          }
    }

脚本不仅不像我想要的那样停在第二个注释行,而且似乎没有退出点并等待Expect超时。

随机样本ACL供参考:

ip access-list extended OUTSIDE
 remark ##### DENIED HOSTS #####
 deny   ip host 2.2.2.2 any
 deny   ip host 9.9.9.9 any
 deny   ip host 8.7.6.5 any
 deny   ip host 5.6.7.8 any
 deny   ip host 5.5.5.5 any
 deny   ip host 4.4.4.4 any
 deny   ip host 3.3.3.3 any
 remark ########################
 permit tcp any any eq 22
 deny   ip any any
 permit ip host 2.3.5.1 any

我基本上想要解析从2.2.2.2到3.3.3.3的地址,但是一旦脚本到达第二个注释行就退出。

parsing expect cisco command-line-interface
3个回答
2
投票

使用exp_continue,最好添加我们想要终止的情况。因此,如果退出案件到达,我们可以从期望终止。否则,显然timeout将会发生。

EG

expect{ 
    “p” {send “\r\r\r”; exp_continue} 
    “+” {incr foo; exp_continue} 
    “i” {puts "test"; exp_continue} 
    “quit” exit 
}

正如您所看到的,如果“退出”这个词出现,那么它就会退出。

让我们来问你的问题。你需要在单词时退出 'remark ########################'到了。但是,如果我们编码,

expect {
   "remark ##### DENIED HOSTS #####\r\n" {
      expect {

            "remark ########################" {exit}
            -re {(\d+\.\d+\.\d+\.\d+)} {
                                    set ip "${ip}$expect_out(0,string)"
                                    puts "-->$ip"
                                    set ip {}
                                    exp_continue
                    }
            }
    }
}

程序将终止expect,而ip解析正在进行中。

您可以更好地获取整个输出并尝试将其解析为单独的变量,以避免在期望中产生开销,而不是这样做。

send "show run | section ip access-list extended OUTSIDE\r\n"
expect {
    -re {deny\s+ip\s+host\s+(.*)remark} { puts "match found" } 
    timeout {puts "timeout happened"}
}

现在我们有匹配,它将在变量expect_out(1,string)中可用。

然后我们可以在变量中执行regexp并解析ip地址。

puts [ regexp -inline -all {\d.\d.\d.\d} $expect_out(1,string) ]

您可以尝试另外一种方法,如下所示。您可以简单地获取整个输出,然后按照下面的方式执行regexp,而不是按预期执行正则表达式。

send "sh run | section ip access-list extended OUTSIDE\r"
#Assuming your router's hostname is `Router`
expect "Router#"
#output will hold the command output.
set output  expect_out(buffer)
puts $output
set ip_list [regexp -inline -all {\d.\d.\d.\d} $output]
foreach ip $ip_list { 
    puts $ip
}

0
投票

感谢Dinesh !!!

在这里重新发布最终的工作代码(或Dinesh提供的代码的混合),这样就不会丢失在上面的所有文本中(因此我可以比评论部分更容易格式化)。

send "show run | section ip access-list extended OUTSIDE\n"

expect -re {remark(.*)remark}
set output $expect_out(buffer)
#puts $output
puts "\r"
set ip_list [regexp -inline -all {\d.\d.\d.\d} $output]
foreach ip $ip_list {
  puts $ip
}

我评论了第一个投注线,但在测试时将其留在那里以查看实际存储在$output中的内容。

这是从路由器CLI解析的ACL:

ip access-list extended OUTSIDE
 remark ##### DENIED HOSTS #####
 deny   ip host 2.2.2.2 any
 deny   ip host 9.9.9.9 any
 deny   ip host 8.7.6.5 any
 deny   ip host 5.6.7.8 any
 deny   ip host 5.5.5.5 any
 deny   ip host 4.4.4.4 any
 deny   ip host 3.3.3.3 any
 remark ########################
 permit tcp any any eq 22
 deny   ip host 82.28.82.28 any
 permit ip host 2.3.5.1 any

我知道,这是一个完全复杂的ACL,但它对测试非常有用。

解析ACL后,这是Expect脚本输出:

2.2.2.2
9.9.9.9
8.7.6.5
5.6.7.8
5.5.5.5
4.4.4.4
3.3.3.3

第二个ACL备注行之后的任何/所有IP地址将根据需要被忽略!

谢谢Dinesh!


0
投票

为什么不使用perl与Net :: Telnet :: Cisco?

https://metacpan.org/pod/Net::Telnet::Cisco

© www.soinside.com 2019 - 2024. All rights reserved.