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

for loop expect results differents between interactive and script

在这个 link 我已经阅读了 for loop management for except 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 在将脚本传递给 expect 之前扩展了您放入脚本的 here-doc 中的变量。来自 bash 联机帮助页:

The format of here-documents is:

[n]<<[-]word
        here-document
delimiter

无参数和变量扩展、命令替换、算术 对 word 执行扩展或路径名扩展。如果任何部分 word 被引用,delimiter 是在 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 脚本通常包含自己的反斜杠,并且事情会变得非常丑陋和复杂。但是,最好是这样做:

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

请注意,这确实意味着从 bash 传递变量有点尴尬。但是你会从大大提高的编码理智中获益。