Expect: No Such Variable

Expect: No such variable

Escape any special characters such as the dollar sign by proceeding them with a backslash, so your code becomes

set mystring "\$THIS_IS_MY_STRING%"

No Such Variable When Using While Loop in Expect

This expect pattern has not matched:

expect -re {^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})\..*$} {
puts -nonewline $fileId $expect_out(0,string)
set initTime $expect_out(1,string) $expect_out(2,string) $expect_out(3,string) $expect_out(4,string) $expect_out(5,string)
}

You would know if it did match because you would get a syntax error: the set command takes only one or two arguments, and you have given it 6.

Add exp_internal 1 to a line before the spawn command, and expect will show you verbose debugging to let you know how your patterns are or are not matching.

To solve the set syntax error, you probably want

    set initTime [getTime $expect_out(1,string) $expect_out(2,string) $expect_out(3,string) $expect_out(4,string) $expect_out(5,string)]

Also, in the if condition, be aware that $initTime will be smaller than $currentTime , so {$initTime - $currentTime > 300} will never be true, so your loop will be infinite.

Quoting issue with expect script

You have the shell variable $VPN_PASSWORD in an unquoted heredoc, so the shell will substitute the value. Suppose VPN_PASSWORD='foo$bar' => Then expect will see: send "foo$bar\r" and you'll get can't read "bar": no such variable. The solution is to use {braces} instead of double quotes, so that expect will not attempt to expand the "inner" variable.

send {$VPN_PASSWORD}; send "\r"

You need a separate send "\r" because putting \r inside the braces will remove its special meaning, and Tcl won't let you do send {$VPN_PASSWORD}"\r"

Here's a demo:

$ VPN_PASSWORD='foo$bar'
$ expect <<END
send_user "$VPN_PASSWORD\n"
END
can't read "bar": no such variable
while executing
"send_user "foo$bar\n""
$ expect <<END
send_user {$VPN_PASSWORD}; send_user "\n"
END
foo$bar

In Tcl, braces act like single quotes in the shell: everything inside them are literal characters.


It might be cleaner to use the environment to pass the values. Here it is implemented as a shell function

vpnconnect() {
expect <<'END'
set timeout 30
spawn /opt/cisco/anyconnect/bin/vpn -s connect $env(VPN_HOST)
expect "Username:*"
send "\r"
expect "Password:*"
send "$env(VPN_PASSWORD)\r"
expect {accept? [y/n]:*}
send "y\r"
expect eof
END
}

how to pass shell variable into expect within shell script

Be careful what you are talking about. We have shell variables and we have exported shell variables a.k.a. environment variables. In your code, you have an environment variable, because you export it.

I answer here therefore for accessing environment variables from within the expect program. If you are really concerned about shell variables, please clarify this in your posting.

First, I strongly recommend to use ALL UPPERCASE names for environment variables. Having lower case in the name of an environ might or might not work, depending on the concrete case.

Now assume I have an environment variable FOO, and I want to access it within expect. This can be done in two ways, using the builtin array env:

$::env(FOO)
[set ::env(FOO)]

BTW, in cases like yours, you do not need the double-colon; for instance $env(FOO) would do the same. However, if you get used to write the ::, you will be on the safe side in case you have to maintain more complex expect programs.

TCL (expect): can't read NF (from awk): no such variable

I think your script is trying to expand the variable $NF with it's value before shooting that command through send. $NF isn't set in your shell since it's internal to awk, which hasn't had a chance to even run yet and so it's balking.

Try escaping that variable so it is treated as a string literal and awk will be able to use it when it comes time for awk to run:

send "cat moo.txt | grep QUACK * | awk 'NF>1{print \$NF}' meow.txt >> bark.txt "


Related Topics



Leave a reply



Submit