eval—Good, Bad, And Ugly

It is occasionally useful to dynamically generate expect commands. By that I mean that the commands themselves are not prewritten in a script but rather are generated while the script is running.

As an example, suppose you want to wait for a particular pattern (”pat1“) and optionally look for another pattern (”pat2“) depending on whether a variable (”v2“) is 1 or 0. An obvious rendering of this logic is as follows:

if {$v2} {
    expect pat1 act1 pat2 act2
} else {
    expect pat1 act1
}

This works. However, lengthy lists of patterns and actions can make this code difficult to maintain. If you want to make a change to an expect command, you will have to make it twice. The odds of a programming error are going to go up.

Even worse, this solution does not extend well if you add another pattern that is dependent on another variable. You will need to have four expect commands to cover all the possibilities. Additional variables quickly cause this technique to become totally unmanageable.

It is tempting to store the patterns and actions into variables which are later appended to the remaining patterns; however, this must be done with care. Examine this incorrect attempt:

if {$v2} {
    set v2pats "pat2 act2"
} else {
    set v2pats ""
}
if {$v3} {
    set v3pats "pat3 act3"
} else {
    set v3pats ""
}

expect pat1 act1 $v2pats $v3pats  ;# WRONG

In the expect command, the patterns in v2pats and v3pats are listed as separate arguments. expect interprets v2pats as a pattern and $v3pats as ...

Get Exploring Expect now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.