using expect
热身小脚本
function myscp
{
local FNAME=$1
local UNAME=$2
local HNAME=$3
local PASSWD=$4
local FNAME_REMOTE=$5
expect <
set timeout 5
set e 0
while 1 {
expect {
“*(yes/no)?” { send “yes\r” }
“*assword:” { if {\$e == 1} { send_user “\nPassword error!\n”; exit 1 }; set e [expr \$e+1]; send “$PASSWD\r” }
timeout { send_user “Connect timeout!\n”; exit 1 }
eof { exit 0 }
}
}
EOF
}
Expect是一个控制交互式程序的工具。他用非交互的方式实现了所有交互式的功能
Expect语言是基于Tcl的。Tcl实际上是一个子程序库,这些子程序库可以嵌入到程序里从而提供语言服务。 最终的语言有点象一个典型的 Shell语言。里面有给变量赋值的set命令,控制程序执行的if,for,continue等命令,还能进行普通的数学和字符串操作。当然了,还可以用exec来调用Unix程序。所有这些功能,Tcl都有。Tcl在参考书籍 Outerhour[3][4]里有详细的描述。
Expect是在Tcl基础上创建起来的,它还提供了一些Tcl所没有的命令。spawn命令激活一个Unix程序来进行交互式的运行。 send命令向进程发送字符串。expect命令等待进程的某些字符串。 expect支持正规表达式并能同时等待多个字符串,并对每一个字符串执行不同的操作。 expect还能理解一些特殊情况,如超时和遇到文件尾。
expect命令和Tcl的case命令的风格很相似。都是用一个字符串去匹配多个字符串。(只要有可能,新的命令总是和已有的Tcl命令相似,以使得该语言保持工具族的继承性)。下面关于expect的定义是从手册[5]上摘录下来的。
expect patlist1 action1 patlist2 action2…..
该命令一直等到当前进程的输出和以上的某一个模式相匹配,或者等到时间超过一个特定的时间长度,或者等到遇到了文件的结束为止。
如果最后一个action是空的,就可以省略它。
每一个patlist都由一个模式或者模式的表(lists)组成。如果有一个模式匹配成功,相应的action就被执行。执行的结果从expect返回。
被精确匹配的字符串(或者当超时发生时,已经读取但未进行匹配的字符串)被存贮在变量expect_match里面。如果patlist是eof 或者timeout,则发生文件结束或者超时时才执行相应的action.一般超时的时值是10秒,但可以用类似”set timeout 30″之类的命令把超时时值设定为30秒。
下面的一个程序段是从一个有关登录的脚本里面摘取的。abort是在脚本的别处定义的过程,而其他的action使用类似与C语言的Tcl原语。
expect “*welcome*” break
“*busy*” {print busy;continue}
“*failed*” abort
timeout abort
模式是通常的C Shell风格的正规表达式。模式必须匹配当前进程的从上一个expect或者interact开始的所有输出(所以统配符*使用的非常)的普遍。但是,一旦输出超过2000个字节,前面的字符就会被忘记,这可以通过设定match_max的值来改变。
expect命令确实体现了 expect语言的最好和最坏的性质。特别是,expect命令的灵活性是以经常出现令人迷惑的语法做代价。除了关键字模式(比如说eof,timeout)那些模式表可以包括多个模式。这保证提供了一种方法来区分他们。但是分开这些表需要额外的扫描,如果没有恰当的用 ["]括起来,这有可能会把和当成空白字符。由于Tcl提供了两种字符串引用的方法:单引和双引,情况变的更糟。(在Tcl里面,如果不会出现二义性话,没有必要使用引号)。在expect的手册里面,还有一个独立的部分来解释这种复杂性。幸运的是:有一些很好的例子似乎阻止了这种抱怨。但是,这个复杂性很有可能在将来的版本中再度出现。为了增强可读性,在本文中,提供的脚本都假定双引号是足够的。
为“Tk”的工具箱如何简洁地表达 GUI 解决方案。

