Newbie - passing variable number of vars to expect script 
Author Message
 Newbie - passing variable number of vars to expect script

Hello -

Let me start out by saying I'm rather new to expect so I'm sure
there's a way to do this I've not seen or found yet.

I've got a script where I pass an unknown number of vars to an expect
script.  Is there some way to handle this in expect?  I've tried a few
things and nothing seems to really work.  For now I'm just handling 10
vars, if there's more than 10 - bummer.  I know I could write it out
to a file, then read it in once I'm in the expect script, but I'd
perfer to come up with a better solution to this than these offer.

thanks,
Chris



Sat, 04 Feb 2006 09:34:52 GMT  
 Newbie - passing variable number of vars to expect script


: Hello -
:
: Let me start out by saying I'm rather new to expect so I'm sure
: there's a way to do this I've not seen or found yet.
:
: I've got a script where I pass an unknown number of vars to an expect
: script.

Hi Peter,

I don't know anything about Expect, but in tcl you can pass an unknown
number of arguments to a script by using "args" as an argument.  Will that
work in Expect?

proc myScript {args} {
    foreach arg $args {
        puts $arg
    }

Quote:
}

myScript arg1 arg2 arg3 arg4 arg5

Jeff



Sat, 04 Feb 2006 09:52:07 GMT  
 Newbie - passing variable number of vars to expect script
:

:: Hello -
::
:: Let me start out by saying I'm rather new to expect so I'm sure
:: there's a way to do this I've not seen or found yet.
::
:: I've got a script where I pass an unknown number of vars to an expect
:: script.
:
:Hi Peter,
:
:I don't know anything about Expect, but in tcl you can pass an unknown
:number of arguments to a script by using "args" as an argument.  Will that
:work in Expect?
:
:proc myScript {args} {
:    foreach arg $args {
:        puts $arg
:    }
:}
:
:myScript arg1 arg2 arg3 arg4 arg5
:
:Jeff

  Expanding on Jeff's example, notice that args has
a special meaning as long as it's the last argument
in the proc's definition.  It can be passed any number
of elements and they will be stored as a Tcl list.
Also, unlike other arguments, it is legal for args to
have 0 elements.

proc myScript {name id args} {
    foreach arg $args {
        puts "$name $id info: $arg"
    }

Quote:
}

myScript Bob 123 one two three
myScript Mary 456 "one two three" 4 5 6
myScript John 789 "7 8 9" "and this string"
myScript Jill "none listed" "7 8 9" defunct

--
  _ _    ____
 //\/\ike ||uxford



Sat, 04 Feb 2006 23:11:18 GMT  
 Newbie - passing variable number of vars to expect script

Quote:

> I've got a script where I pass an unknown number of vars to an expect
> script.  Is there some way to handle this in expect?  I've tried a few
> things and nothing seems to really work.  For now I'm just handling 10
> vars, if there's more than 10 - bummer.  I know I could write it out
> to a file, then read it in once I'm in the expect script, but I'd
> perfer to come up with a better solution to this than these offer.

Others have already responded as to how to have a *procedure* accept a
variable number of arguments. But I interpreted your question as asking if
you can pass an arbitrary number of command-line arguments to a *script*
when you invoke it. The answer is "yes," both in Expect and pure Tcl.

Tcl automatically stores all of the script-level arguments as a list in the
pre-defined global variable "argv", and provides a count of the arguments in
the pre-defined global variable "argc". This is much like the argc and argv
parameters in the main() procedure of a C program, except that Tcl does
*not* include the program/script name as the first argument in its "argv" or
include the program/script name in its "argc" count. If you really need to
know the name of the script (or just the executable, if you simply invoke an
interactive Tcl interpreter), it is automatically stored in the pre-defined
global "argv0" variable.

So, a really quick example that simply prints out all this information:

puts "argv0 = $argv0"
puts "argc = $argc"
set i 0
foreach arg $argv {
    puts "argv element $i = $arg"
    incr i

Quote:
}

- Ken Jones, President
  Avia Training and Consulting
  www.avia-training.com
  866-TCL-HELP (866-825-4357) US Toll free
  415-643-8692 Voice
  415-643-8697 Fax


Sun, 05 Feb 2006 00:00:12 GMT  
 Newbie - passing variable number of vars to expect script
Ken,

Based on your code, I tried to expand it so I could reference the
vars.  I "think" I put everything in an array, however I can't
reference anything in said array.

I have a file with a varying number of "vars" on each line.  The first
is a hostname, the rest are interfaces.  There may just be a couple or
there may be over fifty (per line).  I need to load this file into an
array (or something), then be able to reference each entity in the
array (or whatever) within a loop.

For example, I'll load the array, then somehow spawn a telnet session
to array(0), then within a loop jack with each interface until I reach
the end of the array.  I saw that there is a "array size array_name"
command so I can figure out how big each array (line) is.

Your code:

Quote:

> puts "argv0 = $argv0"
> puts "argc = $argc"
> set i 0
> foreach arg $argv {
>     puts "argv element $i = $arg"
>     incr i
> }

My code now (just trying to reference the array at this point):

#!/usr/local/bin/expect
# program al3.exp

set i 0
foreach arg $argv {
   puts "argv element $i = $arg"
set thing(i) "$arg"
   incr i

Quote:
}

set n 2
puts $n
puts  $thing($n)

When I do:
./al3.exp a b c ddd

I get:

argv element 0 = a
argv element 1 = b
argv element 2 = c
argv element 3 = ddd
2
can't read "thing(2)": no such element in array
    while executing
"puts $thing($n)"
    (file "./al3.exp" line 12)

I'm guessing I can't build the array like this.  I don't care if I get
an array or list...

Help???  Am I on the right track?

thanks!

Pete



Sun, 12 Feb 2006 08:59:41 GMT  
 Newbie - passing variable number of vars to expect script
Hi Peter,

Quote:

> My code now (just trying to reference the array at this point):

> #!/usr/local/bin/expect
> # program al3.exp

> set i 0
> foreach arg $argv {
>    puts "argv element $i = $arg"
> set thing(i) "$arg"

This sets the array element with the key "i" not the one with the key
$i.

Quote:
>    incr i
> }

If you add here

  parray thing

you get a good debugging dump of your array.  That should help
understand what you have.

This is of course just an exercise, I guess.  Note though, that arrays
of this kind (indexed with integers from 0..max) are not often used in
Tcl.  If you want such a C-like array in Tcl, just build a list and
use lindex to reference elements.  It's more efficient and gets you
more idiomatic Tcl-like code.

benny



Sun, 12 Feb 2006 20:03:40 GMT  
 Newbie - passing variable number of vars to expect script
OK, I've now shifted gears as mgmt is getting impatient....

Trying to use a list.  I'm reading the file in, everything is looking
fine, but just found out I can't use a variable for an index.  Someone
please tell me there is a way around this....

#!/usr/local/bin/expect
  set datafile [open "al.tmp" "r"]
  set uid "pg0"
  set passwd "pgpass"
set console_prompt ">$"            ;# Variable for console prompt
set enable_prompt  "#$"            ;# Variable for enable prompt
set config_prompt  "#$"  ;# Variable for config prompt
set config_line  "#$"  ;# Variable for config prompt

while {[gets $datafile line] != -1} {
set len [llength $line]
set routerid [lindex $line 0]

for {set i 1} {$i <=[expr [llength $line]]} {incr i} {
set interface [lindex $line $i]
puts $interface

spawn telnet [lindex $line 0]

###  Problem is here!
I log in here, but problem is how can I get interface to change from
within telnet session OR reference [lindex $line i]???

Quote:
}
}

The only workaround I've found is telnet to device, jack with current
interface, then exit & change interface (I think) and go back in -
there's got to be a better way!

thanks,
Pete



Sun, 12 Feb 2006 21:07:36 GMT  
 Newbie - passing variable number of vars to expect script
Hi Peter,

First the important things:

Quote:
>         spawn telnet [lindex $line 0]

>         ###  Problem is here!
>         I log in here, but problem is how can I get interface to
>         change from within telnet session OR reference [lindex $line
>         i]???

I don't understand the problem.  You have opened your telnet session
here.  Why can't you use a variable?  Can you show an example of code
that didn't work?  The rest of the code doesn't do anything much yet,
so that can't be part of the problem.

Try something simple, let's drop the scaffolding for a moment and
concentrate on the problem with which you want help.  Write down
exactly those things that we need to understand the problem.
Currently you have the equivalent of:

  set routerid "your.router.name"
  set interfaces [list "iface1" "iface2" "iface3"]

  foreach interface $interfaces {
      spawn telnet $routerid
      # do something
      # close telnet session
  }

First change, to clean up resources, you probably need:

  foreach interface $interfaces {
      set spawn_id [spawn telnet $routerid]
      # do something
      close $spawn_id
  }

Second change to consider: Do you really want to re-connect to the
router every time?  If not, you want

  set spawn_id [spawn telnet $routerid]
  foreach interface $interfaces {
      # do something
  }
  close $spawn_id

Next, what is that code that you can't get to work, and which goes
where I wrote "# do something"?

Fine print:

Quote:

> Trying to use a list.  I'm reading the file in, everything is
> looking fine, but just found out I can't use a variable for an
> index.

Index into what?  I don't understand, try slowly (getting impatient
yourself won't get results).  Tcl lets you use a variable in any place
where you can use a literal.  There may be a matter of giving the
right level of quoting.

Quote:
>  Someone please tell me there is a way around this....

> #!/usr/local/bin/expect
>   set datafile [open "al.tmp" "r"]
>   set uid "pg0"
>   set passwd "pgpass"
> set console_prompt ">$"            ;# Variable for console prompt
> set enable_prompt  "#$"            ;# Variable for enable prompt
> set config_prompt  "#$"  ;# Variable for config prompt
> set config_line  "#$"  ;# Variable for config prompt

Are these variables part of your problem?  You never use them yet.
Also you should get into the habit of escaping the $ signs, if they do
not refer to variables.

Quote:
> while {[gets $datafile line] != -1} {
> set len [llength $line]
> set routerid [lindex $line 0]

> for {set i 1} {$i <=[expr [llength $line]]} {incr i} {
> set interface [lindex $line $i]
> [...]

Indent your code correctly.  You will loose time getting confused if
you don't.

Quote:
> while {[gets $datafile line] != -1} {
>     set len [llength $line]
>     set routerid [lindex $line 0]
>     for {set i 1} {$i <=[expr [llength $line]]} {incr i} {
>         set interface [lindex $line $i]
>         puts $interface

>         spawn telnet [lindex $line 0]

>         ###  Problem is here!
>         I log in here, but problem is how can I get interface to change from
>         within telnet session OR reference [lindex $line i]???

>     }
> }

Line-by-line comments:

Quote:
> while {[gets $datafile line] != -1} {

You get a line from your datafile.  Can you explain what format your
datafile has and where the data comes from?  This should than go into
an explaining comment in the code.

Quote:
>     set len [llength $line]

You are treating the string you read as a list.  Is that safe?  In
general if you can not garantee that, you may want to use something
like

      set params [split $line " "]

And than use the list $params instead of the raw string.

Quote:
>     set routerid [lindex $line 0]

So your first item in the list is a router address.

Quote:
>     for {set i 1} {$i <=[expr [llength $line]]} {incr i} {
>         set interface [lindex $line $i]

The rest is a list of interfaces.  It's more Tcl-like to use foreach
if you do not want to access a single item but want to iterate over a
list, like

      foreach interface [lrange $line 1 end] {

Quote:
>         puts $interface

>         spawn telnet [lindex $line 0]

You want to use your variable $routerid here, like

          spawn telnet $routerid

benny



Sun, 12 Feb 2006 23:13:03 GMT  
 Newbie - passing variable number of vars to expect script
:Ken,
:
:Based on your code, I tried to expand it so I could reference the
:vars.  I "think" I put everything in an array, however I can't
:reference anything in said array.
:
:I have a file with a varying number of "vars" on each line.  The first
:is a hostname, the rest are interfaces.  There may just be a couple or
:there may be over fifty (per line).  I need to load this file into an
:array (or something), then be able to reference each entity in the
:array (or whatever) within a loop.
:
:For example, I'll load the array, then somehow spawn a telnet session
:to array(0), then within a loop jack with each interface until I reach
:the end of the array.  I saw that there is a "array size array_name"
:command so I can figure out how big each array (line) is.
:
:Your code:
:
:>
:> puts "argv0 = $argv0"
:> puts "argc = $argc"
:> set i 0
:> foreach arg $argv {
:>     puts "argv element $i = $arg"
:>     incr i
:> }
:>
:
:My code now (just trying to reference the array at this point):
:
:#!/usr/local/bin/expect
:# program al3.exp
:
:set i 0
:foreach arg $argv {
:   puts "argv element $i = $arg"
:set thing(i) "$arg"
:   incr i
:}
:set n 2
:puts $n
:puts  $thing($n)
:
:When I do:
:./al3.exp a b c ddd
:
:I get:
:
:argv element 0 = a
:argv element 1 = b
:argv element 2 = c
:argv element 3 = ddd
:2
:can't read "thing(2)": no such element in array
:    while executing
:"puts $thing($n)"
:    (file "./al3.exp" line 12)
:
:I'm guessing I can't build the array like this.  I don't care if I get
:an array or list...
:
:Help???  Am I on the right track?
:
:thanks!
:
:Pete

Try changing:
    set thing(i) "$arg"
to:
    set thing($i) $arg

--
  _ _    ____
 //\/\ike ||uxford



Sun, 12 Feb 2006 23:35:42 GMT  
 Newbie - passing variable number of vars to expect script

Quote:

>OK, I've now shifted gears as mgmt is getting impatient....

>Trying to use a list.  I'm reading the file in, everything is looking
>fine, but just found out I can't use a variable for an index.  Someone
>please tell me there is a way around this....

>#!/usr/local/bin/expect
>  set datafile [open "al.tmp" "r"]
>  set uid "pg0"
>  set passwd "pgpass"
>set console_prompt ">$"            ;# Variable for console prompt
>set enable_prompt  "#$"            ;# Variable for enable prompt
>set config_prompt  "#$"  ;# Variable for config prompt
>set config_line  "#$"  ;# Variable for config prompt

>while {[gets $datafile line] != -1} {
>set len [llength $line]
>set routerid [lindex $line 0]

>for {set i 1} {$i <=[expr [llength $line]]} {incr i} {
>set interface [lindex $line $i]
>puts $interface

>spawn telnet [lindex $line 0]

>###  Problem is here!
>I log in here, but problem is how can I get interface to change from
>within telnet session OR reference [lindex $line i]???

>}
>}

>The only workaround I've found is telnet to device, jack with current
>interface, then exit & change interface (I think) and go back in -
>there's got to be a better way!

                        .
                        .
                        .
I agree:  there must be a better way.

This thread confuses me.  I'm unsure what to advise about
management impatience; if time truly is important to them,
your organization should consider buying training (Ken
Jones does a bang-up job with Expect) and/or consulting.
Your source code looks like that of a good programmer who's
inexperienced with Expect; if that's true, it's unclear
how pressure from above will accelerate your success.

If the point is that you and your employer *do* want to
grow your expertise with Expect, and you've chosen
comp.lang.tcl as the vehicle you'll try for now, I have
a few suggestions.  Anything you can do to "reduce" your
problem <URL: http://wiki.tcl.tk/RequestHelp > encourages
quicker responses from the most accomplished readers here.

In particular, the post I've quoted above seems to have
at least a couple of issues.  First, you *can* use a
"variable for an index", if I understand your intent; I
encourage you to experiment with
  set my_index flower
  set my_array(flower) See?
  puts "Is '$my_array($my_index)' what you expect?"

Second--at least I think it's a distinct matter--I have
no idea what you mean by "interface to change from
within telnet session".  I urge you to make as small an
example of the symptom as you can, so all of us reading
can focus on what you're truly after.
--


Business:  http://www.Phaseit.net
Personal:  http://phaseit.net/claird/home.html



Sun, 12 Feb 2006 23:37:55 GMT  
 
 [ 15 post ] 

 Relevant Pages 

1. Expect Script - Pass Variables to Perl

2. passing vars to shell script

3. passing vars to awk script

4. Set expect script variables via a korn shell script

5. Starting Multiple Expect Scripts from a Single Expect Script

6. Expect scripts within expect scripts

7. Expect script calling Expect script

8. expect :checking amount of parameters passed to script

9. expect script to enter pass phrase in pgp

10. Passing variable field number to gawk

11. passing functions with variable number of arguments as procedure arguments

12. passing variables to expect 1.1

 

 
Powered by phpBB® Forum Software