📄 00000019.htm
字号:
流程控制 <BR> <BR> tcl支持分支和循环。分支语句可以使用if和switch实现。if语句的和C语言类似,如 <BR> <BR> if { $ x < 0 } { <BR> <BR> set y 10; <BR> <BR>} <BR> <BR> 注意判断子句也需要使用花括号。 <BR> <BR> 与C语言一样,tcl的if语句也可以使用else和elseif。 <BR> <BR> switch语句的用法有点类似这样: <BR> <BR> switch $x { <BR> <BR> 0 { set y 10;} <BR> <BR> 10 { set y 100;} <BR> <BR> 20 { set y 400;} <BR> <BR>} <BR> <BR> 与C的switch语句不同,每次只有符合分支值的子句才被执行。 <BR> <BR> 循环命令主要由for,foreach和while构成,而且每一个都可以使用break和continue <BR>子句。 <BR> <BR> for语句的格式有点类似这样: <BR> <BR> for { set i 0} {$i < 10} { incr i} {puts $i} <BR> <BR> 将会输出从1到9的整数。 <BR> <BR> 如果用while循环,这个句子可以写成 <BR> <BR> while {$i < 10 } { <BR> <BR> puts $i; <BR> <BR> incr i; <BR> <BR>} <BR> <BR> foreach是对于集合中的每一个元素执行一次命令,大致的命令格式是 <BR> <BR> foreach [变量] { 集合 } { <BR> <BR> 语句; <BR> <BR>} <BR> <BR> 例如 <BR> <BR> % foreach j { 1 3 5} { <BR> <BR> put $j; <BR> <BR>} <BR> <BR>1 <BR> <BR>3 <BR> <BR>5 <BR> <BR> 函数 <BR> <BR> 如同在一般的编程语言里面一样,在tcl里面也可以定义函数,这是通过proc命令实现 <BR>的: <BR> <BR> proc my_proc {i}{ <BR> <BR> puts $i; <BR> <BR>} <BR> <BR> 这样就定义了一个名字叫proc的函数,它只是在终端显示输入变元的内容。 <BR> <BR> 要使用这个函数,简单地输入它的名字: <BR> <BR> % my_proc { 5 } <BR> <BR> 5 <BR> <BR> 如果变元的数目是0,只要使用空的变元列表,例如 proc my_proc {} {语句;} <BR> <BR> <BR> 尽管tcl还可以处理更复杂的过程,但是我们不再介绍了,例如文件的读写以及tk图形 <BR>语言,因为我们处理tcl的主要目标就是理解expect,对于更复杂的编程工作,我们建议 <BR>你使用perl。 <BR> <BR> 11.1.2 expect <BR> <BR> expect是建立在tcl基础上的一个工具,它用来让一些需要交互的任务自动化地完成。 <BR>我们首先从一个简单的例子开始,如同在这一节一开始就提到的,我们想设置一个自动 <BR>的文件下载程序。 <BR> <BR> 我们看一看这样的一个例子脚本: <BR> <BR> #! /usr/bin/expect <BR> <BR> spawn ftp 202.199.248.11 <BR> <BR> expect "Name" <BR> <BR> send "ftp\r" <BR> <BR> expect "Password:" <BR> <BR> send "nothing\r" <BR> <BR> expect "apply" <BR> <BR> send "cd /pub/UNIX/Linux/remoteX\r" <BR> <BR> expect "successful." <BR> <BR> send "bin\r" <BR> <BR> expect "set to I" <BR> <BR> send "get exceed5.zip\r" <BR> <BR> expect "complete." <BR> <BR> send "quit\r" <BR> <BR> 这个是什么意思?呵呵,就是个自动下载程序。第一行说明这个程序应该调用/usr/b <BR>in/expect去执行,然后的就是expect命令。 <BR> <BR> 察看expect的手册页面(man expect)可以得到一个很长的expect说明,可惜其中关于 <BR>expect的语法仍然介绍的不够。一般来说,expect主要用在需要自动执行人机交互的过 <BR>程中,例如fsck程序,这个程序会不断地提问"yes/no",像这样的命令就可以用expect <BR>来完成。 <BR> <BR> spawn语句在expect脚本中用于启动一个新的进程,在我们的程序中,spawn ftp 202 <BR>.199.248.11就是去执行ftp程序,接下来,就是expect和send的指令对了。 <BR> <BR> 每一对expect和send指令代表一个信息/回应。如果这样说不好理解的话,那么可以看 <BR>一看ftp的具体执行过程: <BR> <BR> ftp 202.199.248.11 <BR> <BR> Connected to 202.199.248.11. <BR> <BR> 220 mail.asnc.edu.cn FTP server (BeroFTPD 1.3.3(3) Sun Feb 20 15:52:49 CST <BR> 2000. <BR> <BR> Name (202.199.248.11:wanghy): <BR> <BR> 显然,一旦连接成功,服务器会返回一个Name(202.199.248.11:wanghy):的字符串来 <BR>要求客户给出用户名。expect语句简单地在返回信息中查询你给出的字符串,一旦成功 <BR>就执行下面的命令,现在,expect " Name"已经成功地找到了Name字符串,接下来可以 <BR>执行send命令了。 <BR> <BR> send命令比expect命令更简单,它简单地向标准输入提交你设定的字符串,现在设置 <BR>为send "ftp\r"表示等到登录信息之后就给出一个输入ftp回车,也就是标准的登录过 <BR>程。 <BR> <BR> 下面的行与这些行完全一样,只是机械地等待服务器的回应,并且提交自己的输入。 <BR> <BR> 要使用这个expect脚本,你只需要将它设置为可执行的属性,然后执行它,expect就 <BR>会执行你需要的服务。 <BR> <BR> 由于expect是tcl的扩展,所以你在expect文件中可以象tcl脚本一样设置变量和程序 <BR>流程。 <BR> <BR> 现在我们看一看我们还能够如何改进我们的expect脚本。ftp命令可能会失败,比如远 <BR>端的机器可能会无法提供服务,或者在启动ftp命令时本地机器发生问题。为了处理这一 <BR>类的问题,我们可以使用expect的timeout选项来设置超时的话expect脚本自动退出: <BR> <BR> #! /usr/bin/expect <BR> <BR> spawn ftp 202.199.248.11 <BR> <BR> expect { <BR> <BR> timeout exit <BR> <BR> Connect <BR> <BR>} <BR> <BR> ……………… <BR> <BR> 注意这里面使用的花括号。它的含义是使用一组并列表达式。使用并列表达式的主要 <BR>原因是这样:如果使用下面的指令对: <BR> <BR> expect timeout <BR> <BR> exit <BR> <BR> 那么由于expect脚本是顺序执行的,那么当程序执行到这个expect的时候就会阻塞, <BR>所以程序会一直等待到timeout然后退出。并列表达式则是相当于switch的行为,只要列 <BR>出的几项内容有一项得到满足,expect命令就得到满足,于是程序可以正常执行。上面 <BR>的脚本表示,如果连接ftp的时候发生了超时,那么就退出,否则,一旦发现Connect应 <BR>答,说明服务器已经正常了,那么就可以继续运行了。 <BR> <BR> 我们可以看看用tcl能够对我们的expect脚本提供什么帮助。我们可以设置让expect脚 <BR>本不断地连接远端服务器的服务,直到正常建立连接开始,为此,我们可以把建立连接 <BR>的命令放在一个循环里面,并且根据回应的不同自动选择重新输入命令还是继续执行: <BR> <BR> spawn ftp <BR> <BR> while {1} { <BR> <BR> expect "ftp>" <BR> <BR> send "o 202.199.248.11\r" <BR> <BR> expect { <BR> <BR> "Connected" break <BR> <BR> "refused" { sleep 10} ; <BR> <BR> } <BR> <BR>} <BR> <BR> 这里使用了我们在tcl语言中讲到的while和break命令,熟悉C的读者应该很容易看出 <BR>它的行为:不断地等待ftp>提示符,在提示符下面发送连接远端服务器的命令,如果服 <BR>务器回应是refused(连接失败),就等待10秒钟,然后开始下一次循环;如果是Conne <BR>cted,那么就跳出循环执行下面的命令。sleep是expect的一个标准命令,表示暂停若干 <BR>秒钟。 <BR> <BR>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -