使用期望脚本将多行放在一行上
putting multiple lines on one line using expect script
我写了一个 expect 脚本来验证我在 cisco 路由器上是否有静态路由。我需要输出行全部出现在同一行,即使变量匹配多行
以下命令适用于 cisco 设备:
example1#sh run | i ip route
ip route 169.254.0.1 255.255.255.255 Dialer1
ip route 169.254.0.2 255.255.255.255 Dialer2
example1#
这里是 expect 脚本:
set hostname "example1"
set model "cisco1841"
send "sh run \| i ip route\r" ; sleep 5
expect {
-re {\r\nip\s+route.*} {
set route "$expect_out(0,string)"
set f [open file.csv a]
puts -nonewline $f $hostname,$model,$route
puts $f "\r"
close $f
}
timeout {
set route "no static route"
set f [open file.csv a]
puts -nonewline $f $hostname,$model,$route
puts $f "\r"
close $f
}
}
这里变量$route
ip route 169.254.0.1 255.255.255.255 Dialer1
ip route 169.254.0.2 255.255.255.255 Dialer2
example1#
正在验证输出文件,这不是我所期望的。参数“-nonewline”不起作用。该文件总是换行。
这里是输出文件:
example1,cisco1841,ip route 169.254.0.1 255.255.255.255 Dialer1
ip route 169.254.0.2 255.255.255.255 Dialer2
example1#
我做了一个测试,问题是因为变量在行尾没有'\n\r'。
测试 - 正常
set route "ip route 169.254.0.1 255.255.255.255 Dialer1
ip route 169.254.0.2 255.255.255.255 Dialer2
example1#"
测试 - 正常
set route "ip route 169.254.0.1 255.255.255.255 Dialer1 \
ip route 169.254.0.2 255.255.255.255 Dialer2 \
example1#"
输出文件正常
example1,cisco1841,ip route 169.254.0.1 255.255.255.255 Dialer1 ip route 169.254.0.2 255.255.255.255 Dialer2 example1#
如何使用 expect 为每个设备匹配多行并将输出保存在同一行?
默认情况下,puts
命令在字符串后输出一个换行符,但可以通过指定 -nonewline
开关来抑制此功能。 它永远不会删除已在传递的输入字符串中可用的任何现有换行符
在你的例子中,变量 route
已经嵌入了换行符,从而导致它以这种方式打印。
您可以在 route
变量中用 space 替换所有换行符,或者将它们拆分为列表,然后将其写入文件。
puts [regsub -all {\n} $route " "]
再观察一次。您在发送一些命令后使用了 sleep
命令。
send "sh run \| i ip route\r" ; sleep 5
那么您期望 \r\nip\s+route.*
当前符合您的需求。假设,如果输出很大或需要更多时间才能完成,那么它可能会失败。为了有一个安全的方法,你可以使用 exp_continue
来匹配每个出现的行。
我写了一个 expect 脚本来验证我在 cisco 路由器上是否有静态路由。我需要输出行全部出现在同一行,即使变量匹配多行
以下命令适用于 cisco 设备:
example1#sh run | i ip route
ip route 169.254.0.1 255.255.255.255 Dialer1
ip route 169.254.0.2 255.255.255.255 Dialer2
example1#
这里是 expect 脚本:
set hostname "example1"
set model "cisco1841"
send "sh run \| i ip route\r" ; sleep 5
expect {
-re {\r\nip\s+route.*} {
set route "$expect_out(0,string)"
set f [open file.csv a]
puts -nonewline $f $hostname,$model,$route
puts $f "\r"
close $f
}
timeout {
set route "no static route"
set f [open file.csv a]
puts -nonewline $f $hostname,$model,$route
puts $f "\r"
close $f
}
}
这里变量$route
ip route 169.254.0.1 255.255.255.255 Dialer1
ip route 169.254.0.2 255.255.255.255 Dialer2
example1#
正在验证输出文件,这不是我所期望的。参数“-nonewline”不起作用。该文件总是换行。
这里是输出文件:
example1,cisco1841,ip route 169.254.0.1 255.255.255.255 Dialer1
ip route 169.254.0.2 255.255.255.255 Dialer2
example1#
我做了一个测试,问题是因为变量在行尾没有'\n\r'。
测试 - 正常
set route "ip route 169.254.0.1 255.255.255.255 Dialer1
ip route 169.254.0.2 255.255.255.255 Dialer2
example1#"
测试 - 正常
set route "ip route 169.254.0.1 255.255.255.255 Dialer1 \
ip route 169.254.0.2 255.255.255.255 Dialer2 \
example1#"
输出文件正常
example1,cisco1841,ip route 169.254.0.1 255.255.255.255 Dialer1 ip route 169.254.0.2 255.255.255.255 Dialer2 example1#
如何使用 expect 为每个设备匹配多行并将输出保存在同一行?
默认情况下,puts
命令在字符串后输出一个换行符,但可以通过指定 -nonewline
开关来抑制此功能。 它永远不会删除已在传递的输入字符串中可用的任何现有换行符
在你的例子中,变量 route
已经嵌入了换行符,从而导致它以这种方式打印。
您可以在 route
变量中用 space 替换所有换行符,或者将它们拆分为列表,然后将其写入文件。
puts [regsub -all {\n} $route " "]
再观察一次。您在发送一些命令后使用了 sleep
命令。
send "sh run \| i ip route\r" ; sleep 5
那么您期望 \r\nip\s+route.*
当前符合您的需求。假设,如果输出很大或需要更多时间才能完成,那么它可能会失败。为了有一个安全的方法,你可以使用 exp_continue
来匹配每个出现的行。