收藏 分享(赏)

TCL、TK学习交流文档.ppt

上传人:fmgc7290 文档编号:8119639 上传时间:2019-06-09 格式:PPT 页数:48 大小:334.50KB
下载 相关 举报
TCL、TK学习交流文档.ppt_第1页
第1页 / 共48页
TCL、TK学习交流文档.ppt_第2页
第2页 / 共48页
TCL、TK学习交流文档.ppt_第3页
第3页 / 共48页
TCL、TK学习交流文档.ppt_第4页
第4页 / 共48页
TCL、TK学习交流文档.ppt_第5页
第5页 / 共48页
点击查看更多>>
资源描述

1、119-Tcl-Overview.ppt 1998/01/03,Tcl经验点滴文集,文档结构,Tcl介绍 “Hello World” 程序及扩展 变量 数据类型 特殊字符 数据结构 控制结构 程序结构 语法要点 对数据库操作实例( oracle ) Socket编程实例 ktcl 文件及其冲值卡自服务修改密码例程 一些建议 后附,我们为什么用Tcl?,Tcl是什么?1、Tool Command Language2、Terminal Control LanguageTcl是一种解释型的脚本语言。脚本解释器为tclsh,同时它也是一个shell环境。Tcl和C语言有着天然的亲缘关系,即相近的数据类

2、型与控制结构;通过规范的API,能够比较方便的用C进行Tcl的扩展开发。 Tcl能做什么?1、Tcl首先是作为一种简单的命令脚本语言而发明,以便控制和调用各个系统命令。2、与C相似的数据类型与控制结构,使其具有处理高级事务的能力。3、强大的文本处理能力。4、扩展能力达到GUI、网络、OOP等各个方面。 我们为什么用Tcl?1、因为亚信用它。2、确实好用,功能强大:从KAP加速引擎到html(ktcl)标签。为Web Server配置动态加速引擎KAP,TCL-plugin的安装 。3、快速学习、快速开发。,Tcl与C的比较,老套,一个著名的程序世界上最著名的程序是什么?猜一猜:是“Hello

3、World!”,下面是tcl版的程序(设$ 为Linux系统提示符)$ cat hello.tcl#!/usr/bin/tclshputs “Hello World!”$ hello.tclHello World!$ shell方式(新开一个终端界面,调试命令行重要方式。)以上是以程序的方式运行;tcl也可以运行于shell的形式(提示符%)$ tclsh% puts “Hello World!”Hello World!% exit$,老套(续),Tcl脚本程序的结构1、在第一行指定解释器#!/usr/bin/tclsh或如下写法#!/bin/sh# the next line restart

4、s using tclshexec tclsh “$0“ “$ “ 2、注释的标记为#如:# This is a comment sentence3、句与句(包括注释句)之间以“换行”或“;”分隔如:# Following a sentenceputs “line 1“puts “line 2“ ; # Another comment,老套(续),puts 命令看tcl的帮助,是这样说:puts 向一个channel(相当于C里的句柄)写这里的channel可以是标准输出、一个打开的文件、一个打开的socket、甚至一个打开的Unix管道等等、等等。到后面我们的socket例程可以看到具体的使

5、用含义。 puts 命令用法puts ?-nonewline? ?channelId? string 两个?表示之间的内容为可选。如上文的puts “Hello World!”向“屏幕(标准输出)”写字符串,可以写成puts stdout “Hello World!”-nonewline是puts命令的一个option,它的意思是“输出内容后不换行”,另一个老套,第二著名的程序$ cat hello2.tcl#!/usr/bin/tclshputs -nonewline “Please input your name: ”set Name gets stdin ;# You can write

6、 it as : gets stdin Name puts “Hello, $Name!” 运行$ hello2.tclPlease input your name: MarkHello Mark!$,另一个老套,Sh与Tcl输入输出对比$more hello2.sh#! /bin/shechoechoecho “Please input your name: c“read usernameecho “Hello, $username !“ 运行$ hello2.shPlease input your name: MarkHello ,Mark!$,另一个老套,新的内容符号对“”gets 命令

7、set 命令$ 符号 表明中的内容为列表“”表明“”中的内容为列表但其中的特殊字符要解释 如,$, () () array的下标,另一个老套(续),新的内容在前一页,有一个语句:set Name gets stdin 符号对“”的意思是:执行里面的命令,用结果替换这个组合,类似于C语言中的函数调用。上文这个句子的含义是:把“gets stdin”的值赋给变量Name。gets 的语法:gets channelId ?varName? gets 从一个channel取一个行到指定变量;同时它本身也返回这个行,所以gets还有第二种用法:gets stdin Name,变量,变量是程序的基础。 变

8、量:变量名、变量值 变量名:任何字符串都可作为变量名,如下所示,皆可作变量名Name变量1“A Variable“甚至空格或一个“空”串也可以作为变量名。 变量赋值:set Name Markset Line “Hello World!“set 变量名 值与gets类似,命令set同时也返回值。引号的作用是让里面的内容为一个整体(因为中间有空格),其本身不是实际数据;如果要把引号作为数据引用,在其前面用转义符号 ,变量(续),变量的值:变量的值以符号“$”加变量名来展开,如:$Name$变量1$“A Variable”注意,在展开变量名之前必须保证此变量已被赋过值,否则在展开时会报错“no s

9、uch variable”。 举例,请在一个tcl环境里逐一试试如下命令:% set Name Mark% puts $Name% set x puts% set y $Name% $x “Hello $y!“由于tcl是解释型语言,在执行每个句子前都要先展开变量,上文最后一行句子就形成一种动态代码的效果。由此类推,可以实现动态过程、动态调用等代码形式,在某些地方是很有用的。,数据类型,tcl 的数据类型实际上只有一种:字符串所以在tcl中的变量没有类型转换或类型匹配问题,所有的“数据”都是以字符串的形式存在。那么,tcl如何进行数值计算?我如何计算并输出一个小数? 数值计算tcl是支持数值计

10、算的(包括数学函数),不过仅能用在expr 命令中% set x 100% set y expr $x + 1% incr y -2% expr double($x)% set y expr $x * 2.3% expr abs(sin($x) “数据类型”输出一个命令format,其格式串参数类似C语言。% set z format “This is %-8.2f !“ $yThis is 230.00 !,特殊字符,有涵义的字符$ 展开变量的值 展开一个命令(或调用过程)的值“” 内容作为一个整体,里面支持$ 的作用 内容作为一个整体,但里面不支持$ 及转义字符的作用 转义符,让特殊字符失

11、去特殊涵义,转为纯粹可现字符;同时让一些可现字符转为特殊字符,如 n t r 等 例子在tcl环境中逐一试试以下命令% set x 100% puts $x% puts “$x“% puts $x% puts expr $x * 2.3% puts “It is expr $x * 2.3“% puts It is expr $x * 2.3% puts “It is expr $x * 2.3 n“,数据结构- 列,列是tcl里功能非常强大非常灵活的一种数据结构:1、各个值按序排列% set x list arg1 arg2 arg32、或者按指定分隔符拆分一个字符串% set Str “1

12、,2,3“% set x split $Str “,“ 列的元素可以是任何东西,字符串、空格、“空”、甚至一个列。 列的概念比较复杂,下面例子,体会一下:% set x “1 2 3 4“% llength $x% split $x “ “% set x “ 1 2 3 4“% llength $x% split $x “ “% set x list 1 2 3 “ 4 % llength $x% split $x “ “,数据结构-数组,数组提供一个或多个值到另一个值的映射,或者这种映射的集合:简单说,某个数组的某个下标对应某个值,和C语言不同的是,tcl里的数组下标可以是“任何”字符串,

13、“空”。 试试下面命令:% set Data(1) 1.0% set Data(-2.3) abc% set Data(Name) Mark% set Data() “Hello,“% set Data( ) “a space“ ;# wrong # args: should be “set varName ?newValue?“% set Data(“My Name“) “Mark !“ % puts “$Data() $Data(“My Name“)“% set Data(hello,$Data(Name) “$Data() $Data(“My Name“)“% puts $Data(he

14、llo,Mark) 数组还有很多相关的操作,可参见命令 array,控制结构-条件分支,终于来到if语句了,没有if语句怎么能有程序?建议形式:if expr . . .或者:if expr1 . . . elseif expr2 . . . else . . .表达式的值应该为逻辑值,表达式支持逻辑运算(与C相似),注意之间要有空格。 例子if ($x = “Mark”) & ($y = 1) puts Hello!,控制结构-条件分支(续),一点体会1、等式一定要写两个等号2、如果表达式一端有字符串常量,一定用引号括起3、注释,设有如下代码if $x = “Mark” puts Hello

15、!如果想临时改条件,可否这样写?#if $x = “Mark” if $x = “John” puts Hello!试试便知。4、整个if是一个句子,里面必要的分隔符不能省,控制结构-循环,for 循环按照C语言的教程,if语句后应该是for循环了。for start_expr test_condition next or step body;for set x 0 $x10 incr x puts “x is $x“循环里可以有break ,continue。实际上,for 的语法形式很简单,你完全可以用C的语法来考虑它。表达式也可以是复合的:% for set x 0; set y 10

16、$x 3 incr y puts “$x - $y“在写程序时需要注意的是整个句子里,变量有的地方带$,有的地方不带$,这是经常容易笔误的地方。,控制结构-循环(续),while 循环while test_condition body;set x 0while $x10 puts “x is $x“incr x在实际程序中,while 用到较多的地方是处理文件,set fpIn open $FileName r while eof $fpIn != 1 set CurLine gets $fpIn if $CurLine = “” continue. . .,控制结构-循环(续),前面有一个和

17、C程序不同的地方:如果文件已经读完最后一行,继续while eof $fpIn != 1 在C和tcl里条件都会通过但在句子 set CurLine gets $fpIn 里tcl 会返回并设CurLine 为文件的最后一行C 会返回并设 CurLine 为空所以在tcl程序里在其后加上了如下判断:if $CurLine = “” continue附,C里通常的写法如下:fgets( CurLine, MAXSIZE, fpIn);while ( !feof( fpIn ) ) . . .fgets( CurLine, MAXSIZE, fpIn );,控制结构-循环(续),foreach 循

18、环foreach 是tcl里常用的循环方法,因为它和list这个功能强大的数据结构有关系:foreach Item ItemList body;set NameList “John Mark Jack Bill.Gates “foreach Name $NameList puts “He is $Name“foreach的扩展:foreach Name Position John Engineer Mark Manager puts “$Name is $Position“foreach Name “John Mark“ Position “Engineer Manager“ puts “$N

19、ame is $Position“,控制结构-循环(续),数据集循环我们经常需要从数据库里读取一批数据进行处理,这里也是一个循环的过程。目前,tcl支持对oracle和sybase的操作。set sqlline “select field1, field2 from table1 where ”orasql $DBHandle $sqlline orafetch $DBHandle “CalledProc 1 2”每返回一个记录,以对应的字段域做参数调用过程CalledProc或者:orafetch $DBHandle puts 1puts 2. . .直接把执行体写在后面。每返回一个记录,执

20、行其后的操作。可以有break和continue。注意:符号及参数?的用法在执行体内好象不能写注释,会有语法错误(?),程序结构,一般形式#!/aitools/bin/tclsh8.0source OtherProgramFileglobal Varibles1, . VariblesNload LibraryFileproc ProcName arg1 arg2 argn global Var1 Var2 Var. . .return RetStringif $argc = 0 puts “Usage: $argv0 FileIn FileOut ”return -1set SomeVar

21、PorcName Arg1 Arg2 . . .Arg return 0,程序结构(续),source 可以把一个外部的tcl文件在此处展开(执行),我们大家熟知的一个文件就是etc/aiip.cfg,它里面其实就是一段tcl程序,设置了一个名为AIIP的数组 global 指定某些变量是全局可用的。在tcl里,主程序里的变量并不是全局可用的,必须在主程序或过程里用global说明后,才能在过程里引用。亚信aiobs 程序里经常在source aiip.cfg 后紧接着就是global AIIP load 加载外部函数库。比如oratcl(tcl的oracle支持库)。aiobs 很多用C开发

22、的代码都可以被tcl加载,只要符合一定的规则。这也是tcl和C亲缘关系的一个证明。 proc 说明一个子过程,后面接过程名、参数列表、执行体。需要注意的是,过程的参数列表应该和调用处的参数一致。但例外的是,如果过程的参数只写一个,它就可以以list的形式接收多个入口参数。,程序结构(续),proc (续)proc F1 arg1 agr2 arg3 . . .proc F2 args set arg1 lindex $args. . .set SomeVar F1 Arg1 Arg2 Arg3 set SomeVar F2 Arg1 Arg2 Arg3 proc 只能返回字符串,这是一个不太灵

23、活的地方。如果只返回单个值还好说,反正tcl里只有一种数据类型,return 回来就是了。在aiobs里,一个过程经常要一次返回多个数据,就象C里返回一个结构一样,如何实现?用list的方法,在调用返回的字符串里用lindex解出各个单元。proc F1 arg1 arg2 arg3 . . .set RetString Val1lappend RetString Val2,程序结构(续),proc (续)return RetStringset SomeVal F1 1 2 3 set RetV1 lindex $SomeVal 0set RetV2 lindex $SomeVal 1. .

24、.注意,proc的调用是传值调用,在主程序调用是要给具体的数据或变量的值。proc 支持递归调用,不知有多深,反正做个100!没问题。主程序只是为了整齐,前面的几个部分如source、load 、proc等都写在文件的前部,实际上可以灵活些,只要在运行的逻辑顺序上不要发生“未定义的.”就可以。主程序入口时会带来几个变量,常用的有数组 env 系统的环境变量本程序名 argv0,程序结构(续),主程序(续)入口参数个数 argc (不包括本程序名,与C不同)入口参数列 argv (不包括本程序名)如果调用程序:$ hello.tcl Mark John那么在程序里:puts $arg0 ;# h

25、ello.tclputs $argc ;# argc = 2puts $argv ;# “Mark John”puts lindex $argv 0 ;# Markputs lindex $argv 1 ;# John,语法要点,append 和 lappend append 向一个变量里追加字符串append a $b 和 set a $a$b 效果一样,但append 效率更好一些(省内存?)lappend 向一个列里追加元素set a “1 2 3“lappend a 4 array 数组操作太多的操作类型了,看看help吧。 catch 捕获tcl操作的错误if catch open

26、$someFile w fid puts stderr “Could not open $someFile for writingn$fid“exit 1如果操作正常,变量fid被设置成里面操作的返回值,If语句不成立;如果操作不正常,if语句成立,同时变量fid被设成操作的错误信息。这个命令很有用,因为一个普通的tcl命令会因为某种原因的错误使整个程序down,如果我们不想让程序停止,用catch来处理是个好办法。,语法要点(续),clock 时钟clock seconds 返回一个以秒为单位的整型值clock format ClockValue -format FormatString 把

27、一个“秒”时间返回成指定格式的字符串。格式串的语法同C,参见helpclock format clock seconds -format “%Y%m%d %H:%M:%S“clock scan 从一个“时间”字符串里返回“秒”时间。一般来说,tcl的版本越高,支持的时间“格式”越多。clock scan “12/31/2001“clock scan “20010821“ ;# clock scan “12/31/2001 23:10:0“clock scan “Wed Feb 21 12:03:10 2001“clock scan “next day“ -base clock secondsc

28、lock scan “next month“用法太复杂了,要多实验多体会。,语法要点(续),expr计算表达式,包括数学函数、数值类型转换。数值计算只能在expr里。它也支持数据类型转换例:set x 100set y expr $x * 2 set z expr $x * 2.1set zz expr $x.00 + 1set yy expr double($x)file可以取得文件系统的有关信息,执行有关操作。 glob按返回符合指定条件的文件名list,语法要点(续),incr简单的计算变量的加减incr xincr y -1 info返回一些有关程序的信息。我常用于判断一个变量是否存在

29、:if !info exists VarName set VarName $SomeVar. . . join 和splitsplit $SomeString 把一个字符串解成listsplit $SomeString “,“ 以,为分隔符把一个字符串解成listjoin $SomeList 把一个list合成一个字符串join $SomeList “,“ 以,为分隔符把一个list合成一个字符串,语法要点(续),list 及相关操作list arg1 argn 把各个参数合成一个listllength $SomeList 返回list的长度(元素个数)lindex $SomeList 0 返

30、回list的第一个元素lindex $SomeList end 返回list的最后一个元素 ;# end是list操作的保留字lindex $SomeList expr llength $SomeList - 1 什么意思?linsert $SomeList Index $SomeVar 在Index(元素位置 ,如上文0,end)处插入一个元素。lrange $SomeList first last 从list的first位置到last位置返回一个子列。lreplace $SomeList first last $SomeVar 从list的first位置到last位置的元素替换成新值lso

31、rt ?option? $SomeList 对list排序lsearch $SomeList $SomeVar 在list里搜索是否有某元素,经常用到。join 、split、foreach 就不说了 open 打开文件或管道,简直和C一样。相关操作close 、flush、puts、gets、read、seek、eof、tell,语法要点(续),pid 返回本进程的id,有用吗?我做后台程序时用过。 regexp 对字符串进行正则表达式分析regexp ?switches? exp string ?matchVar? ?subMatchVar subMatchVar .?如果在 string

32、 之后指定了补充的参数,则把它们作为变量的名字对待,把关于 string 中匹配exp 的那部分的信息返回到其中。MatchVar 将被设置为匹配全部 exp 的 string 的范围。第一个 subMatchVar 将包含与 exp 中最左的圆括号中的子表达式相匹配的 string 中那部分字符,下一个 subMatchVar 将包含与exp 中从左到右的下一个圆括号中的子表达式相匹配的 string 中那部分字符,以此类推。 如:set x 01062501658regexp “010(.*)“ $x y zputs “$x $y $z“ scan 从字符串里读数据,同C的语法scan s

33、tring format varName ?varName .? scan 10,20 %d,%s x y set 和 unset set 设置或初始化一个变量unset 释放一个变量(有时很有用的) socket打开一个tcp连接。亚信obs对外接口全是用Tcl写的。接下来有个socket例程。,语法要点(续),string 对字符串操作,是tcl里最常用。常用的操作:string first string1 string2 ?startIndex? 在string2的startInddex位置开始查找第一次匹配string1的位置,例如:string first a 0a23456789a

34、bcdef 5 ;# 返回10string index $SomeStr charIndex 返回SomeStr 中charIdex处的字符。string is class $SomeStr 返回字符串的类型,低版本tcl不支持string is digit 01062501658 ;#返回1string length $SomeStr 返回字符串长度string range $SomeStr first last 返回字符串中first 到last部分string trim $SomeStr ?Chars? 在字符串的两头删除Chars集中的字符,如果Chars没有说明,则删除空格、tab、

35、回车、换行。 string trimleft $SomeStr ?Chars? 在字符串的左边删string trimright $SomeStr ?Chars? 在字符串的右边删注意:这三个trim可别弄混了,否则. . .,语法要点(续),switch 一个多分支的结构,和C差不多。操作很多,常用的形式:switch $SomeVar 1 - 2 puts “This is 1 or 2 “3 puts “This is 3“ default puts “Other“ % set elements “o c n p li“; % foreach element $elements swit

36、ch $element n puts gas;li puts solid; default 但不支持C中类似结构:case 1: puts(“This is 1“); /* 这里没有break */case 2: puts(“This is 2“);break;case 3: puts(“This is 3“);break;,对oracle操作,初始化及连接 load libOratcl25.soset dbuser “aiobs5/obs5aiAIOBS5“if catch oralogon $dbuser logon puts “connected failed,check your or

37、acle user name and password“exit 1if catch oraopen $logon DBHandle puts “open cursor failed“exit 1if catch oraopen $logon DBHandle2 ;#可以开多个事务puts “open cursor failed”; exit 1set DBSQL orasqlset DBNEXT orafetchset DBCOMMIT oracommitset DBCLOSE oraclose,对oracle操作(续),select 操作 set sql “ select bms_coms

38、tomer_id, bms_customer_name ” append sql “ from bms_customer ”. . .$DBSQL $DBHandle $sql$DBNEXT $DBHandle set Id 1set Name 2puts 2. . . 或者proc Aproc Id Name . . .$DBNEXT $DBHandle “Aproc 1 2”,对oracle操作(续),其它操作 set sql “ insert into $TableName ”append sql “ ( field1, .) ”. . .If catch $DBSQL $DBHandl

39、e $sql errinfo puts “some wrong, $errinfo”$DBCLOSE $DBHandlereturn -1$DBCOMMIT $DBHandle 注意catch的应用。在实际应用中如果有大量数据操作,可以分批提交以加快速度。 预编译操作$DBSQL $DBHandle “update bms_subscription set bms_user_password =:user_password where bms_user_name = :user_name “ -parseonlyorabindexec $DBHandle :user_password $use

40、r_password :user_name $user_name 请看例程callered_stat.tcl,Socket编程,Socket server1、定义 、启用端口;2、监听端口,收受请求request;3、处理事务返回结果response信息。 Socket client1、连接server socket通道channelId;2、发送请求;3、接受请求结果。 例程$ pwd/home/db2inst1/jiawx/testdir$ ls -l ./*./bin:-rwxr-xr-x 1 db2inst1 db2iadm1 1114 Apr 15 10:44 socketClien

41、t.tcl-rwxr-xr-x 1 db2inst1 db2iadm1 533 Apr 15 10:46 socketServer.tcl./etc:total 8-rw-r-r- 1 db2inst1 db2iadm1 262 Apr 15 10:41 progTest.tcl-rw-r-r- 1 db2inst1 db2iadm1 45 Apr 15 07:04 socket.cfg,Socket编程,Socket server$ more socketServer.tcl#!/usr/bin/tclsh# I have a test! # A simple socket server !

42、 #source /etc/progTest.tclproc accept sock host port fconfigure $sock -buffering lineset request gets $sock#puts $requestputs $sock eval $requestclose $sock# main #socket -server accept 9005vwait x,Socket编程,$ more /etc/progTest.tcl# this is a procedure of counting files bits #proc countBIT filename

43、set rtn exec wc -c $filenamereturn $rtn 启spcket server服务$ socketServer.tcl &1 12843$ $ telnet 0 9005 Trying 0.0.0.0.Connected to 0 (0.0.0.0).Escape character is .Connection closed by foreign host.$ 以上信息表示端口测试成功,Socket编程,Socket client$ more socketClient.tcl #!/usr/bin/tclsh # # I have a test! # # a s

44、imple socket client # # source /etc/socket.cfg #puts $hostId$port if $argc 0)& (lindex $argv 0=“?“) puts “n *“ puts “ This is a simple socket client test ! “puts “n *“ exit 0 else set f lindex $argv 0 # main set s socket $hostId $port fconfigure $s -buffering line puts $s “countBIT $f“ puts read $s,

45、Socket编程,$ more /etc/socket.cfg set hostId 192.168.148.128 set port 9005 $ $ socketClient.tcl /etc/socket.cfg 45 /etc/socket.cfg$,ktcl 文件,ktcl 文件实际上是html文件,里面可以加入标签:使用明细查询结果 proc days_of_month year month if info exists QUERY(bill_type) ;#从上一个页面传来参数,注意用法!set bill_type string trim $QUERY(bill_type) ;#

46、变量在整个文件有效 else set :error_msg “参数bill_type未找到!“:kap:loadpage error.ktclputs “” ;# tcl的输出是标准的html文本,由浏览器显示return 例程chg_cash_card_passwd.html;chg_cash_card_passwd.ktcl,一些编程建议,代码说明(详细请参照VSS:10.设计文档1005.开发规范)文件头:摘要、版权、版本信息、其它(包定义)过程头:摘要、参数、结果 缩进最好用4个空格缩进;如果是单行折返(即用连接的两行,后续行)缩进8个空格 关于 最好在行末;在控制结构里对最好存在,哪怕里面只有一行if $tcl_platform(platform) = “unix” return就不如if $tcl_platform(platform) = “unix” return 清晰的表达式if $x 22 & $y 22) & ($y = 47) 过程必须有return,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报