0

I need to write a script on Expect to read a text file that contains two columns. Column one is the site name (dns) and the second is a router interface that will be used as the source-interface when I perform an FTP function from a Cisco router. Here is the content of the text file (myfile.txt):

site1   Gi0/0/0.44
site2   GigabitEthernet0/0
site3   GigabitEthernet0/0
site4   GigabitEthernet0/0/0
site5   GigabitEthernet0/0/0

Here is my code. It is only able to read the first column. You will see a variable named "source-int", it has not been defined anywhere yet. I just put it in the script as a placeholder.

#!/usr/bin/expect
#
#
set workingdir cisco/rtr
puts stdout "Enter TACACS Username:"
gets stdin tacuserid
system stty -echo
puts stdout "Enter TACACS password:"
gets stdin tacpswd
puts stdout "\nEnter enable password:"
gets stdin enabpswd
system stty echo
#
set RTR [open "$workingdir/myfile.txt" r]
#
while {[gets $RTR dnsname] != -1} {
if {[ string range $dnsname 0 0 ] != "#"} {
        send_user "The value of the router name is $dnsname\n"
        set timeout 10
        set count 0
        log_file -a -noappend $workingdir/session_$dnsname\_$timestamp.log
        send_log "### /START-SSH-SESSION/ IP: $dnsname @ [exec date] ###\n"
        spawn ssh -o StrictHostKeyChecking=no -l $tacuserid $dnsname
expect -ex "TACACS Password: "
send "$tacpswd\r"
expect ">"
send "enable\r"
expect "assword: "
send "$enabpswd\r"
expect "#"
send "config t\r"
expect "#"
send "no ip ftp passive\r"
expect "#"
send "ip ftp username anonymous\r"
expect "#"
send "ip ftp source-interface $souce-int\r"
expect "#"
send "ip ftp password cisco\r"
expect "#"
send "end\r"
expect "#"
send "copy ftp://10.10.10.1/out/customer/ACL.txt flash:\r"
expect "\?"
send "\r"
expect "#"
send "end\r"
expect "#"
send "exit\r"
send_log "\n"
send_log "### /END-SSH-SESSION/ IP: $dnsname @ [exec date] ###\n"
log_file
sleep 5
        }
}
exit

Any assistance is greatly appreciated. Thanks!

PF75
  • 5
  • 2

1 Answers1

0

You can use tcl's regexp command to split the line into 2 words.

if {[regexp {(\S+)\s+(\S+)} "$dnsname" dummy dns interface] == 1} {
    puts "dns=$dns interface=$interface"
}

The regexp code \s matches a whitespace character, and \S a non-whitespace character. The + suffix matches 1 or more of the previous code. The () capture the wanted parts, and they are put by the command into the variables dns and interface.

meuh
  • 11,500
  • 2
  • 29
  • 45
  • Hi Meuh. It seems to be working but I'm a bit confused about this part... **"$dnsname" dummy dns interface**. What is the purpose of "dummy"? it is not being reference anywhere else and without it, the script does not give the expected result. Thanks. – PF75 May 18 '20 at 22:22
  • The regexp command needs a variable into which to store what the pattern matched. In this case it is the whole line (the 2 words and the space between them). We are not interested in this value, but we need to have that variable in the command before we can put the next 2 variables, dns and interface, in which to get the 2 sub-patterns inside the `()`. – meuh May 19 '20 at 05:24
  • Thanks again for your help. – PF75 May 19 '20 at 13:10