for 循环期望交互式和脚本之间的结果不同

问题描述

在此链接中,我阅读了 for 循环管理,除了 https://tcl.tk/man/tcl8.6/TclCmd/for.htm

如果你调用 expect 并将代码粘贴进去,你会得到正确的行为:

@gigi:~$ expect
expect1.1> for {set x 0} {$x<10} {incr x} {
    puts "x is $x"
}+> +> 
x is 0
x is 1
x is 2
x is 3
x is 4
x is 5
x is 6
x is 7
x is 8
x is 9
expect1.2> 

相反,如果您从 bash 脚本传递它,则会出错:

^@gigi:~expect -d << EOD
> for {set x 0} {$x<10} {incr x} {
>     puts "x is $x"
> }
> EOD
expect version 5.45.4
argv[0] = expect  argv[1] = -d  
set argc 0
set argv0 "expect"
set argv ""
executing commands from command file
missing operand at _@_
in expression "_@_<10"
    (parsing expression "<10")
    invoked from within
"for {set x 0} {<10} {incr x} {
    puts "x is "

为什么这个例子的工作方式不同?

解决方法

您遇到的问题是 bash 扩展了 here-doc 中的变量,在将脚本传递给 expect 之前将这些变量放入其中。来自 bash 联机帮助页:

此处文档的格式为:

[n][-]
此处-文档
分隔符

无参数和变量扩展、命令替换、算术 扩展或路径名扩展是对 word 进行的。如果任何部分 word 被引用,分隔符是对 word 引用删除的结果, 并且此处文档中的行未扩展。如果是 未加引号,此处文档的所有行都受参数影响 扩展、命令替换和算术扩展,字符 序列 \ 被忽略,并且必须使用 \ 来引用 字符 \$`

这意味着一种解决方法是使用 expect -d << 'EOD' 而不是 expect -d << EOD

expect -d << 'EOD'
    for {set x 0} {$x<10} {incr x} {
        puts "x is $x"
    }
EOD

另一个(劣等的!)是反斜杠引用 $ 字符;它是低劣的,因为真正的期望脚本通常包含自己的反斜杠,事情会变得非常丑陋和复杂。但是,最好这样做:

将expect 脚本放在它自己的文件中,myfile.exp,并像这样调用它:expect -d -f myfile.exp。试图将 Tcl 代码放在 Bash 脚本中是自找麻烦。

请注意,这确实意味着从 bash 传递变量有点尴尬。但是您可以通过大大提高编码的理智而获益。