0

我编写了一个脚本,如果有足够的可用空间,则将 IOS 文件发送到我的 cisco 设备,如果没有足够的可用空间 - 删除一个文件,直到有。除非 IOS 恰好在一个目录中,否则这一切都很好。

伪代码:

send directory command
parse output and put it in format
flash:c3560-ipservicesk9-mz.150-2.SE7.bin
flash:/testfolder/c3560-ipservicesk9-mz.120-2.SE7.bin

实际代码:

set index 0
send "dir /recursive \n"
expect {
        #this is the new code
        -nocase -re "directory of (\[^\r\]+)" {
                set test $expect_out(1,string)
                exp_continue
        }
        #old code that just grabbed all ios, working
        -nocase -re "(\[^\[:space:\]\]+.bin)" {
                append test ":$expect_out(1,string)"
                set ioses($index) $test
                set index [expr $index + 1]
                exp_continue
        }
        #final case which escapes the exp_continue, and sets the free space
        -nocase -re "\\((.*) bytes free" {set free $expect_out(1,string)}
}

这是“发送目录/递归”的输出示例

Directory of flash:/*

2  -rwx    17620224  Apr 20 2015 00:49:13 +00:00  c3560-ipservicesk9-mz.150-2.SE7.bin
3  -rwx        2236   Mar 1 1993 00:01:02 +00:00  vlan.dat
4  -rwx        4560  Apr 22 2015 14:30:05 +00:00  private-config.text
7  -rwx       32329  Apr 17 2015 23:09:06 +00:00  backup_config
6  -rwx        3096  Apr 22 2015 14:30:05 +00:00  multiple-fs
8  -rwx       32344  Apr 22 2015 14:30:04 +00:00  config.text

Directory of flash:/testfolder

    9  -rwx        2236  Apr 23 2015 02:01:08 +00:00  c3560-ipservicesk9-mz.120-2.SE7.bin

27998208 bytes total (10151936 bytes free)

当我打印出我的数组时,我只有一个值 flash:/testfolder/c3560-ipservicesk9-mz.120-2.SE7.bin"

我的算法显然是错误的,如何解析这些数据?

编辑-

这是我最终得到的代码,尽管 DINESH 的代码也可以

expect {
        -nocase -re "directory of.+#" {
                set input $expect_out(buffer)
                set filesystem $input
                set data [split $filesystem "\r"]
                foreach dat $data {
                        if { [regexp -nocase {directory of} $dat] } {
                                regexp -nocase {directory of (.+)} $dat -> fs
                                regsub -all {/\*} $fs "" fs
                        }
                        if { [regexp -nocase {bin} $dat] } {
                                regexp -nocase { ([^[:space:]]+bin)} $dat -> f
                                if { [regexp {/} $fs] } {
                                        lappend ioses $fs/$f
                                } else {
                                        lappend ioses $fs$f
                                }
                        }
                        if { [regexp -nocase {bytes free} $dat] } {
                                regexp -nocase {\((.*) bytes free} $dat -> free
                        }
                }
        }
}
4

1 回答 1

1

由于您必须匹配多个项目,因此最好匹配所有内容,直到获得 command 的整个输出dir /recursive

send "dir /recursive\r"
expect -re "(.*)<till your prompt>"

在这里,您的提示可以是$or>#。一种通用方法可以像

set prompt "#|>|\\\$"; # Backslashes to match literal dollar sign

expect_out从数组中获得全部内容后,应用regexp并获取结果。

我只是假设输入变量具有全部内容。为了证明这一点,我将它分配给一个变量。

set input "
Directory of flash:/*

2  -rwx    17620224  Apr 20 2015 00:49:13 +00:00  c3560-ipservicesk9-mz.150-2.SE7.bin
3  -rwx        2236   Mar 1 1993 00:01:02 +00:00  vlan.dat
4  -rwx        4560  Apr 22 2015 14:30:05 +00:00  private-config.text
7  -rwx       32329  Apr 17 2015 23:09:06 +00:00  backup_config
6  -rwx        3096  Apr 22 2015 14:30:05 +00:00  multiple-fs
8  -rwx       32344  Apr 22 2015 14:30:04 +00:00  config.text

Directory of flash:/testfolder

    9  -rwx        2236  Apr 23 2015 02:01:08 +00:00  c3560-ipservicesk9-mz.120-2.SE7.bin

27998208 bytes total (10151936 bytes free)

"

# -all => To match all occurrence of the pattern in the given input
# -line => To enable newline-sensitive matching. By default, newline is a 
# completely ordinary character with no special meaning.
# -inline => To get the matched words as a list
set  dirnames [regexp -line -all -nocase -inline {directory of\s(\S+).*} $input]
#puts $dirnames
set filenames [regexp -line -all -inline {\S+\.bin} $input]
#puts $filenames
regexp {(\d+) bytes free} $input ignore freespace

foreach {ignore actualdir} $dirnames filename $filenames {
    //Checking if it contains '/*' or not.
    if {[regsub {/\*} $actualdir {} actualdir]} {
        lappend result $actualdir:$filename
    } else {
        lappend result "$actualdir/$filename"
    }
}   
foreach elem $result {
    puts $elem
}
puts "Free space : $freespace"

输出 :

flash:c3560-ipservicesk9-mz.150-2.SE7.bin
flash:/testfolder/c3560-ipservicesk9-mz.120-2.SE7.bin
Free space : 10151936
于 2015-04-23T07:26:58.493 回答