expect学习笔记-2

来源:互联网 发布:用友会计软件 编辑:程序博客网 时间:2024/05/08 01:21

       Expect需要Tcl语言的支持,要在系统上运行Expect须首先安装Tcl。TCL的全名为Tool Control Language,念作"Tickle",事实上它是一个Scripting Language(俗称脚本语言),也是一个直译器(Interpreter)。由于expect是从Tcl继承下来的,所以也支持Tcl的语法和命令,比如变量声明、流程控制等。
       TCL 语言有四个特色:
       1)跨平台,可在各种系统 (UNIX、Windows、Macintosh 等) 执行 TCL 程序。
       2)强大的字符串处理能力正则表达式,协助程序员使用表达式的规则或样式 (pattern),用来搜寻、比对、粹取或是取代符合样式的复杂字符串。
       3)可用 C 语言开发TCL Extension Library,扩充 TCL 的指令与能力,例如 Tk extension 让 TCL 拥有 GUI Programming 的功能、expect extension用来开发可与应用程序交互式沟通的程序。
       4)已有一大堆可在各式场合发挥效用的 package,诸如各种网络应用(ftp, http、email, dns, msn, icq 等)、图形化接口开发 (TK, BWidget, Tktable, SpecTCL, VisualTCL, ActiveState KOMODO)、对象导向程序开发 (incrTcl, XOTcl, SNIT 等) 以及数据库程序开发 (MetaKit, daFT 等)。
       总结来说,TCL 语言就像是一瓶胶水一般,只要收集可资运用的应用程序与 TCL Package,在这些接口上涂涂抹抹,写个简单的TCL Script (TCL 指令的集合),在短暂的时间内就可组装出一个新工具来。

info
        info命令的几个选项提供了查看变量信息的手段。
        info exists varName 如果名为varName的变量在当前上下文(作为全局或局部变量)存在,返回1,否则返回0。
        info globals pattern 如果没有pattern参数,那么返回包含所有全局变量名字的一个list。如果有pattern参数,就只返回那些和pattern匹配的全局变量(匹配的方式和string match相同)。
        info locals  pattern 如果没有pattern参数,那么返回包含所有局部变量(包括当前过程的参数)名字的一个list,global和upvar命令定义的变量将不返回。如果有pattern参数,就只返回那些和pattern匹配的局部变量(匹配的方式和string match相同)。

global
        对于在过程中定义的变量,因为它们只能在过程中被访问,并且当过程退出时会被自动删除,所以称为局部变量;在所有过程之外定义的变量我们称之为全局变量。TCL中,局部变量和全局变量可以同名,两者的作用域的交集为空:局部变量的作用域是它所在的过程的内部;全局变量的作用域则不包括所有过程的内部。这一点和C语言有很大的不同。如果我们想在过程内部引用一个全局变量的值,可以使用global命令。
        TCL 在执行时会建立一些全域变量,可以利用 info global 列出有哪些全域变量。其中几个比较常用的,像是 argc 存放程序的命令列参数个数,argv0 是目前执行的 TCL Script 名称,argv 则是存放所有命令列参数的list;env 数组存放系统的环境变量,而tcl_version 会告诉你目前的 TCL 版本为何。

set
         用来给变量进行赋值,set fruit Cauliflower,将字符串"Cauliflower"赋值给变量fruit,并使用$fruit访问变量。

command substitution
        命令置换是由 [ ] 括起来的TCL命令及其参数,命令置换会导致某一个命令的所有或部分单词被另一个命令的结果所代替。例如:%set y  [expr 10+100] 
        这里当TCL解释器遇到字符 '[' 时,它就会把随后的expr作为一个命令名,从而激活与expr对应的C/C++过程,并把 'expr' 和变量置换后得到的 '10+110' 传递给该命令过程进行处理。如果在上例中我们去掉[ ],那么TCL会报错。因为在正常情况下,TCL解释器只把命令行中的第一个单词作为看作命令,其他的单词都作为普通字符串处理,看作是命令的参数。

         注意,[ ]中必须是一个合法的TCL脚本,长度不限。[ ]中脚本的值为最后一个命令的返回值,例如:%set y [expr $x+100;set b 300]
        有了命令置换,实际上就表示命令之间是可以嵌套的,即一个命令的结果可以作为别的命令的参数。

if
        语法: if test1 body1 else if test2 body2 else if....  else bodyn
       TCL先把test1当作一个表达式求值,如果值非0,则把body1当作一个脚本执行并返回所得值,否则把test2当作一个表达式求值,如果值非0,则把body2当作一个脚本执行并返回所得值……。例如:

if { $x>0 } { .....} else if {$x==1 } { .....} else if { $x==2 } { ....} else { .....}

        注意,上例中'{'一定要写在上一行,因为如果不这样,TCL 解释器会认为if命令在换行符处已结束,下一行会被当成新的命令,从而导致错误的结果。在下面的循环命令的书写中也要注意这个问题。书写中还要注意的一个问题是if/else 和{之间应该有一个空格,否则TCL解释器会把'if{'作为一个整体当作一个命令名,从而导致错误。

while
        语法为: while test body
        参数test是一个表达式,body是一个脚本,如果表达式的值非0,就运行脚本,直到表达式为0才停止循环,此时while命令中断并返回一个空字符串。例如:假设变量a是一个链表,下面的脚本把a的值复制到b:
set b " "set i [expr [llength $a] -1]while { $i>=0}{ lappend b [lindex $a $i] incr i -1}
for
       语法为: for init test reinit body
       参数init是一个初始化脚本,第二个参数test是一个表达式,用来决定循环什么时候中断,第三个参数reinit是一个重新初始化的脚本,第四个参数body也是脚本。
set b " "for {set i [expr [llength $a] -1]} {$i>=0} {incr i -1} { lappend b [lindex $a $i]}
foreach
        这个命令有两种语法形式
       1、 foreach varName list body
        第一个参数varName是一个变量,第二个参数list 是一个列表(有序集合),第三个参数body是循环体。每次取得链表的一个元素,都会执行循环体一次。下例与上例作用相同:
set b " "foreach i $a { set b [linsert $b 0 $i]}
        2、 foreach varlist1 list1 varlist2 list2 ... Body
        这种形式包含了第一种形式。第一个参数varlist1是一个循环变量列表,第二个参数是一个列表list1,varlist1中的变量会分别取list1中的值。body参数是循环体。varlist2 list2 ...表示可以有多个变量列表和列表对出现。例如:
set x {}foreach {i j} {a b c d e f} { lappend x $j $i}
这时总共有三次循环,x的值为"b a d c f e"。
set x {}foreach i {a b c} j {d e f g} { lappend x $i $j}
这时总共有四次循环,x的值为"a d b e c f g"。
set x {}foreach i {a b c} {j k} {d e f g} { lappend x $i $j $k}

这时总共有三次循环,x的值为"a d e b f g c"。
breakcontinue
        在循环体中,可以用break和continue命令中断循环。其中break命令结束整个循环过程,并从循环中跳出,continue只是结束本次循环。

switch
        和C语言中switch语句一样,TCL中的switch命令也可以由if命令实现。只是书写起来较为烦琐。
        switch命令的语法为: switch  options string { pattern body  pattern body ...}
        第一个是可选参数options,表示进行匹配的方式。TCL支持三种匹配方式:-exact方式,-glob方式,-regexp方式,缺省情况表示-glob方式。-exact方式表示的是精确匹配,-glob方式的匹配方式和string match 命令的匹配方式相同,-regexp方式是正规表达式的匹配方式。

        -glob选项,符合一般shell的通配符方式,使用"* ? [] [!]。

        -regexp选项,在正则表达式中,一些字符具有特殊的含义,下表一一列出,并给予了解释。

        第二个参数string 是要被用来作测试的值,第三个参数是括起来的一个或多个元素对,例:

switch $x {a -b { incr t 1 }c { incr t 2 }default { incr t 3 }}

其中a的后面跟一个'-'表示使用和下一个模式相同的脚本。default表示匹配任意值。一旦switch命令找到一个模式匹配,就执行相应的脚本,并返回脚本的值,作为switch命令的返回值。

eval
        eval命令是一个用来构造和执行TCL脚本的命令,其语法为: eval arg arg ...
        它可以接收一个或多个参数,然后把所有的参数以空格隔开组合到一起成为一个脚本,然后对这个脚本进行求值。例如:
        %eval set a 2

expr
        其中expr是TCL的一个命令,语法为: expr arg ?arg ...?
        两个?之间的参数表示可省,后面介绍命令时对于可省参数都使用这种表示形式。 expr可以有一个或多个参数,它把所有的参数组合到一起,作为一个表达式,然后求值:%expr 1+2*3 。与shell下的expr命令不同,tcl中的expr不需要把操作数和操作符分开作为参数。
lindex
        set file [lindex $argv 0] 变量file被设置为脚本的第一个参数的值,是通过一个Tcl函数lindex来实现的,该函数从列表/数组得到一个特定的元素。[ ] 用来实现将函数lindex的返回值作为set命令的参数。

llength
        语法:llength list
        返回list的元素个数。例:% llength {1 2 {3 4}} 为3。

lappend
        语法:lappend varname value ?value...?
        把每个value的值作为一个元素附加到变量varname后面,并返回变量的新值,如果varname不存在,就生成这个变量。例:

% set a 1 2 3% lappend a 1 2 3

linsert
        语法:linsert list index value ?value...?
        返回一个新串,新串是把所有的value参数值插入list的第index个(0-based)元素之前得到。例:% linsert {1 2 {3 4}} 1 7 8 {9 10}

append incr
         这两个命令提供了改变变量的值的简单手段。append命令把文本加到一个变量的后面,例如:

% set txt hello% append txt "! How are you"

         incr命令把一个变量值加上一个整数。incr要求变量原来的值和新加的值都必须是整数。

%set b 2%incr b 3
0 0