expect用法
 
命令:
         expect - 可编程的交互式程序对话程序。
语法:
         expect [ -dDinN ]    [ -c cmds ]   [   [ -[f|b] ]   cmdfile ]      [   args    ]
介绍:
         expect是一个能够根据某个脚本与交互式程序“对话”的程序。 通过脚本,expect可以知道期望从交互式程序中得到的内容以及应该作出什么样的正确相应。一种解释性的语言提供了分支和高级控制结构以此来引导对话的进行。另外,当有必要时用户可以接管控制权与程序进行直接的交互,然后再将控制权返还给脚本。
         Expectk是 Expect 与 Tk 的混合。 它的行为和 Expect 和 Tk所期望的一样。Expect同样可以直接应用于c或者c++(也就是说,不使用Tcl),参考 libexpect(3)。
         名字“Expect”来自于由于uucp、kermit以及别的调制解调器控制程序而广受欢迎的send/expect序列的思想,然而,与uucp所不同的是, Expect更一般化,因此它可以与别的程序或者任务一起作为用户级别的命令运行。实际上,Expect可以同时与多个程序对话。
          例如,下面就是Expect可以做的几种事情:
              § 让你的电脑回拨,这样你就可以不用支付呼叫费用了。
              §   开始一个游戏(如rogue),如果现在不是游戏最佳的配置,那么就一遍又一遍的重启游戏直到游戏到了最佳的配置,然后把控制台交给你。
              § 运行 fsck ,当 fsck 询问用户的时候,回答 “yes” 或者 “no” 然后将控制权返回给用户。
              § 连接到别的网络或者 BBS (例如, MCI Mail, CompuServe),并且自动的检索你的邮件。因此这就像它是最初发送到你本地的系统一样。
              § 搬运环境变量、当前目录或者rlogin、telnet、tip、su、chgrp时的任何信息。
         shell不能完成这些任务的原因有好几种,然而通过 expect 这些都是可以的。
         一般来讲,expect在运行那些需要程序和用户交互的程序时是非常有用的。所需要的就是将那些交互式的字符通过程序写出来。如果需要的话,Expect 同样可以把控制权返给用户(无须停止被控制的程序)。同样地,用户可以在任意时刻把控制权返还给脚本。
用法:
            Expect 从 cmdfile 中读取命令列表来执行。在某些支持 #! 的系统中Expect 也可以被隐式调用,就是在脚本的第一行加上:
             #!/usr/bin/expect -f
            当然,/usr/bin/expect只是一个例子,使用 expect 的实际路径来代替。
    -c 标志之后的命令在任何脚本之前执行,该命令应当被引用以防止被 shell 破坏。这个选项也可能被使用多次。你也可以使用一次 -c 选项,相应的命令使用分号隔开,命令按照它们在命令行上的顺序执行。
    -d 标志使能一些诊断输出,这些输出包括命令的内部动作,如 expect、interact等命令的内部动作等。这个标志的功能和 Expect 脚本的开始写上 “exp_internal 1” 的功能一样,它同样也能输出 expect的版本。(strace 命令跟踪状态是非常有用的,trace 命令跟踪变量的分配是非常有用的)(使用 Expectk时,使用 -diag选项)
    -f 标志指定命令文件,这个标志是可选的,因为它只是在使用#! 表示法时有用,以便于别的参数可以从命令行提供。默认情况下,命令文件被读入内存然后整体执行,有时也有必要一次读入一行,例如,stdin 就是使用这种方法读取,为了使得任意的文件都可以按照这种方式处理,使用 -b 选项(使用 Expectk时,使用 -buffer 选项).
   如果文件名为 “-” ,那么就从标准输入读取命令。
   -i 标志使得 Expect 交互式的等待命令的输入而不是从文件中读入命令。 提示读到 exit 命令或者 EOF时停止。参照 interpreter, -i 假设没有使用命令文件和 -c 选项。(使用 Expectk时,使用 -interactive 选项)。
   --选项来界定选项的终止,如果你想给交互式程序输入一个和选项重名的参数时这个选项将非常有用。使用 "--" 之后所有的与标志字符相同的字符串将不被 expect 解释。例如, #!/usr/bin/expect --    将会保持 argv 中的参数。
   注意,用于 getopt(3) 和 execve(2) 的常用规范也同样适用于 #!
   如果 $exp_library/expect.rc 文件存在的话,它将被自动的 sourced,除非使用了 -N标志,(使用 Expectk时,使用 -NORC选项)
   -v 选项用来打印 Expect 的版本信息。(使用 Expectk时,使用 -version选项)
   可选的 args 参数被构造成一个列表并被存储在 argv 变量中。 argc 被初始化成 argv 的长度。
   argv0 为脚本的名字。例如,下面的命令将输出脚本的名字以及前三个参数:
       send_user "$argv0 [ lrange $argv 0 2 ]\n"
命令:
         Expect 使用 Tcl ( Tool Command Language ) 。Tcl 提供了流程控制,表达式评估以及其他的几种特性如递归、过程定义等等。这里使用的命令是 Tcl 命令。Expect 支持另外的命令,这在下面将会有描述,除非特别的指定,命令将返回空串。
        命令按照字母表的顺序给出,这样便于查询。 然而,新的用户会发现如果按照 spawn、send、expect 和 interact的顺序叙述的话会更容易一些。
        注意:
        ①对 Expect 和 Tcl 语言介绍的最好的是 “Exploring Expect”。
        ②在本手册中 “Expect” 指的是 Expect 程序本身,而 “expect” 指的是 Expect 程序所包含的expect 命令。
    
      expect [ [ -opts ] pat1 body1 ] ﹍ [ -opts ] patn [ bodyn ]
      一直等待到匹配列表中的一个模式匹配上了 spawn 所产生的进程的输出 或者是指定的等待时间超时 或者是没有一个匹配为止。如果最后一个匹配为空的话,它将被忽略。
     来自于最近 expect_before 命令中的模式在别的模式之前被隐含的使用。 最近的 expect_after 命令中的模式在别的模式之后被隐含的使用。
     如果 expect 的参数超过一行的话,就用花括号将所有的参数括起来,并在没一行末尾使用反斜线连接。在这种情况下,尽管有括号将它们括起来,tcl的通常替换将可能发生。
     如果一个模式是关键字 eof ,the corresponding body is executed upon end-of-file。If a pattern is the keyword timeout, the correspond‐ing body is executed upon timeout. If no timeout keyword is used, an implicit null action is executed upon timeout. 默认的超时时间是30秒,当然你可以使用 “set timeout 30” 将超时时间设置成30秒。如果将超时时间设成 -1 的话,将无限时的等待。 If a pattern is the keyword default, the corresponding body is executed upon either timeout or end-of-file。
      如果一个模式匹配上了, 那么就执行相应的 body。 expect 返回 body 的运行结果。在匹配上了多个模式的情况下,第一个匹配上的模式的 body 将被执行。
      每当有新的输出到来时,expect 将会按照模式在命令行上的顺序进行一一的匹配。因此,你也许想测试一个遗漏的模式,这时你可以将最后一个模式设置成约定好的模式,例如一个 prompt。 在没有 prompt的情况下,你必须使用 timeout(就像你手动的交互一样)。
      使用三种方式来指定模式。 默认情况下,像使用 Tcl 的串匹配命令一样来制动模式。(这样的模式与 c-shell中的正规表达式一样)。 -gl flag may may be used to protect patterns that might otherwise match expect flags from doing so. 任何以 “-” 开头的模式都不采用这种模式指定方式。
      例如,下面的片段用于寻找一个成功的登录。(注意,假设abort是一个已经定义好的过程)
      expect {
        busy                  {puts busy\n ; exp_continue}
        failed                  abort
        " invalid password "   abort
        timeout               abort
        connected
       }
      在第三个模式中的引号是必须的因为它包含了空格,空格将会把模式和动作隔开,具有相同动作的匹配它们的动作需要引用多次, 而在这则表达式的方式中就不用多次使用:
                 expect {
                     busy       {puts busy\n ; exp_continue}
                     -re "failed|invalid password" abort
                     timeout    abort
                     connected
                 }