tcl - Expect script help - capturing data from send command -
i wrote script sends ios files cisco device if there enough free space, if there isn't enough free space- delete file until there is. works fine , dandy unless ios happens in directory.
pseudo code:
send directory command parse output , put in format flash:c3560-ipservicesk9-mz.150-2.se7.bin flash:/testfolder/c3560-ipservicesk9-mz.120-2.se7.bin
actual code:
set index 0 send "dir /recursive \n" expect { #this new code -nocase -re "directory of (\[^\r\]+)" { set test $expect_out(1,string) exp_continue } #old code grabbed 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 escapes exp_continue, , sets free space -nocase -re "\\((.*) bytes free" {set free $expect_out(1,string)} }
here example of output of "send dir /recursive"
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)
when print out array, have 1 value flash:/testfolder/c3560-ipservicesk9-mz.120-2.se7.bin"
my algorithm wrong, how go parsing data?
edit-
this code ended with, although dinesh's code works well
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 } } } }
since have match multiple items, better match content till whole output of command dir /recursive
.
send "dir /recursive\r" expect -re "(.*)<till prompt>"
here prompt can $
or >
or #
. 1 generalized approach can
set prompt "#|>|\\\$"; # backslashes match literal dollar sign
once have whole content expect_out
array, apply regexp
, results.
i assuming input variable having whole content. demonstrate same, have assigned 1 variable.
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 => match occurrence of pattern in given input # -line => enable newline-sensitive matching. default, newline # ordinary character no special meaning. # -inline => matched words 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 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"
output :
flash:c3560-ipservicesk9-mz.150-2.se7.bin flash:/testfolder/c3560-ipservicesk9-mz.120-2.se7.bin free space : 10151936