资源描述
Click to edit Master title style,Click to edit Master text styles,Second level,Third levelcontinued,Fourth level,Fifth level,Tcl,经验点滴,陈昊,亚信科技(中国)有限公司,软件部,PSO,chenhao,119-,Tcl-Overview.,ppt,1998/01/03,文档结构,Tcl,介绍,“,Hello World,”,程序及扩展,变量,数据类型,特殊字符,数据结构,控制结构,程序结构,语法要点,对,oracle,操作,ktcl,文件,一些建议,后附,我们为什么用,Tcl,?,Tcl,是什么?,1、,Tool Command Language,2、Terminal Control Language,Tcl,是一种解释型的脚本语言。脚本解释器为,tclsh,,同时它也是一个,shell,环境。,Tcl,和,C,语言有着天然的亲缘关系,即相近的数据类型与控制结构;通过规范的,API,,能够比较方便的用,C,进行,Tcl,的扩展开发。,Tcl,能做什么?,1、,Tcl,首先是作为一种简单的命令脚本语言而发明,以便控制和调用各个系统命令。,2、与,C,相似的数据类型与控制结构,使其具有处理高级事务的能力。,3、强大的文本处理能力。,4、扩展能力达到,GUI、,网络、,OOP,等各个方面。,我们为什么用,Tcl?,1、因为亚信用它。,2、确实好用,功能强大:从,KAP,加速引擎到,html(ktcl),标签。,3、快速学习、快速开发。,老套,一个著名的程序,世界上最著名的程序是什么?猜一猜:,是“,Hello World!”,,下面是,tcl,版的程序(设,aiobs56,为,Unix,系统提示符),aiobs56 cat hello.tcl,#!/aitools/bin/tclsh,puts“Hello World!”,aiobs56 hello.tcl,Hello World!,aiobs56,shell,方式,以上是以程序的方式运行;,tcl,也可以运行于,shell,的形式(提示符%),aiobs56 tclsh,%puts“Hello World!”,Hello World!,%exit,aiobs56,老套(续),Tcl,脚本程序的结构,1、在第一行指定解释器,#!/,aitools/bin/tclsh,或如下写法,#!/,bin/sh,#the next line restarts using tclsh,exec tclsh$0$,2、,注释的标记为#,如:,#,This is a comment sentence,3、句与句(包括注释句)之间以,“,换行,”,或,“,;,”,分隔,如:,#,Following a sentence,puts“line 1”,puts“line 2”;#Another comment,老套(续),puts,命令,看,tcl,的帮助,是这样说:,puts,向一个,channel(,相当于,C,里的句柄)写,这里的,channel,可以是标准输出、一个打开的文件、一个打开的,socket、,甚至一个打开的,Unix,管道等等、等等。,puts,命令用法,puts?-nonewline?channelId?string,两个?表示之间的内容为可选。如上文的,puts“Hello World!”,向,“,屏幕(标准输出),”,写字符串,可以写成,puts stdout“Hello World!”,-nonewline,是,puts,命令的一个,option,,,它的意思是,“,输出内容后不换行,”,另一个老套,第二著名的程序,aiobs56 cat hello2.tcl,#!/aitools/bin/tclsh,puts-nonewline“Please input your name:”,set Name gets stdin;#You can write it as:gets stdin Name,puts“Hello,$Name!”,运行,aiobs56 hello2.tcl,Please input your name:Mark,Hello Mark!,aiobs56,新的内容,符号对,“,”,gets,命令,set,命令,$符号,另一个老套(续),新的内容,在前一页,有一个语句:,set Name gets stdin,符号对,“,”,的意思是:执行里面的命令,用结果替换这个组合,类似于,C,语言中的函数调用。,上文这个句子的含义是:把,“,gets stdin,”,的值赋给变量,Name,。,gets,的语法:,gets channelId?varName?,gets,从一个,channel,取一个行到指定变量;同时它本身也返回这个行,所以gets还有第二种用法:,gets stdin Name,变量,变量是程序的基础。,变量:变量名、变量值,变量名:任何字符串都可作为变量名,如下所示,皆可作变量名,Name,变量1,“,A Variable”,甚至空格或一个,“,空,”,串也可以作为变量名。,变量赋值:,set Name Mark,set Line“Hello World!”,set,变量名 值,与,gets,类似,命令,set,同时也返回值。,引号的作用是让里面的内容为一个整体(因为中间有空格),其本身不是实际数据;如果要把引号作为数据引用,在其前面用转义符号,变量(续),变量的值:变量的值以符号,“,$,”,加变量名来展开,如:,$,Name,$,变量1,$,“,A Variable”,注意,在展开变量名之前必须保证此变量已被赋过值,否则在展开时会报错,“,no such variable,”,。,举例,请在一个,tcl,环境里逐一试试如下命令:,%,set Name Mark,%puts$Name,%set x puts,%set y$Name,%$x“Hello$y!”,由于,tcl,是解释型语言,在执行每个句子前都要先展开变量,上文最后一行句子就形成一种动态代码的效果。由此类推,可以实现动态过程、动态调用等代码形式,在某些地方是很有用的。,数据类型,tcl,的数据类型实际上只有一种:字符串,所以在,tcl,中的变量没有类型转换或类型匹配问题,所有的,“,数据,”,都是以字符串的形式存在。,那么,,tcl,如何进行数值计算?我如何计算并输出一个小数?,数值计算,tcl,是支持数值计算的(包括数学函数),不过仅能用在,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!”$y,This is 230.00 !,特殊字符,有涵义的字符,$展开变量的值,展开一个命令(或调用过程)的值,“”内容作为一个整体,里面支持$的作用,内容作为一个整体,但里面不支持$及转义字符的作用,转义符,让特殊字符失去特殊涵义,转为纯粹可现字符;同时让一些可现字符转为特殊字符,如,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 arg3,2、,或者按指定分隔符拆分一个字符串,%,set,Str,“1,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,里的数组下标可以是,“,任何,”,字符串,包括空格或,“,空,”,(所以数组的下标对空格敏感,注意)。,试试下面命令:,%,set Data(1)1.0,%set Data(-2.3),abc,%set Data(Name)Mark,%set Data()“Hello,”,%set Data()“a space”,%set Data(“My Name”)“Mark!”,%puts“$Data()$Data(“My Name”)”,%set Data(hello,$Data(Name)“$Data()$Data(“My Name”)”,%puts$Data(hello,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!,如果想临时改条件,可否这样写?,#,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$x 3 incr y ,puts$x-$y,在写程序时需要注意的是整个句子里,变量有的地方带$,有的地方不带$,这是经常容易笔误的地方。,控制结构-循环(续),while,循环,while,test_condition,body,;,set x 0,while$x hello.tcl Mark John,那么在程序里:,puts$arg0 ;#hello.tcl,puts$argc ;#argc=2,puts$argv ;#“Mark John”,puts lindex$argv 0;#Mark,puts 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$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,把一个,“,秒,”,时间,返回成指定格式的字符串。格式串的语法同C,参见help,clock 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 seconds,clock scan“next month”,用法太复杂了,要多实验多体会。,语法要点(续),expr,计算表达式,包括数学函数、数值类型转换。,数值计算只能在expr里。它也支持数据类型转换,例:,set x 100,set y expr$x*2,set z expr$x*2.1,set zz expr$x.00+1,set yy expr double($x),file,可以取得文件系统的有关信息,执行有关操作。,glob,按返回符合指定条件的文件名,list,语法要点(续),incr,简单的计算变量的加减,incr x,incr y-1,info,返回一些有关程序的信息。我常用于判断一个变量是否存在:,if !info exists,VarName,set,VarName$SomeVar,.,join,和,split,split$SomeString,把一个字符串解成list,split,$,SomeString“,”,以,为分隔符,把一个字符串解成list,join$SomeList,把一个list合成一个字符串,join$SomeList “,”,以,为分隔符把一个list合成一个字符串,语法要点(续),list,及相关操作,list arg1 argn,把各个参数合成一个list,llength,$,SomeList,返回,list,的长度(元素个数),lindex,$SomeList,0,返回,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,位置的元素替换成新值,lsort,?option?$SomeList,对,list,排序,lsearch,$SomeList$SomeVar,在,list,里搜索是否有某元素,经常用到。,join,、split、foreach,就不说了,open,打开,文件或管道,简直和,C,一样。相关操作,close,、flush、puts、gets、read、seek、eof、tell,语法要点(续),pid,返回本进程的,id,,有用吗?我做后台程序时用过。,regexp,对字符串进行正则表达式分析,如:,set x 01062501658,regexp“010(.*)”$x y z,puts“$x$y$z”,scan,从字符串里读数据,同,C,的语法,scan string format varName?varName.?,scan 10,20%d,%s x y,set,和,unset,set,设置或初始化一个变量,unset,释放一个变量(有时很有用的),socket,打开一个,tcp,连接,我没用过,但亚信肯定用了,比如短消息网关。,语法要点(续),string,对字符串操作,是,tcl,里最常用。,常用的操作:,string first,string1 string2?startIndex?,在string2的start,Inddex,位置开始查找第一次匹配string1的位置,例如:,string first a 0a23456789abcdef 5 ;#,返回10,string index,$SomeStr charIndex,返回,SomeStr,中,charIdex,处的字符。,string is,class$SomeStr,返回字符串的类型,低版本tcl不支持,string is digit 01062501658 ;#,返回1,string length$SomeStr,返回字符串长度,string range$SomeStr first last,返回字符串中,first,到,last,部分,string trim,$SomeStr?Chars?,在字符串的两头删除,Chars,集中的字符,如果,Chars,没有说明,则删除空格、tab、回车、换行。,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”,但不支持,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.so,set dbuser aiobs5/obs5aiAIOBS5,if catch oralogon$dbuser logon,puts connected failed,check your oracle user name and password,exit 1,if catch oraopen$logon DBHandle ,puts open cursor failed,exit 1,if catch oraopen$logon DBHandle2 ;#,可以开多个事务,puts open cursor failed”;exit 1,set DBSQL orasql,set DBNEXT orafetch,set DBCOMMIT oracommit,set DBCLOSE oraclose,对,oracle,操作(续),select,操作,set sql“select bms_comstomer_id,bms_customer_name”,append sql“from bms_customer”,.,$DBSQL$DBHandle$sql,$DBNEXT$DBHandle,set Id 1,set Name 2,puts 2,.,或者,proc Aproc Id Name ,.,$DBNEXT$DBHandle“Aproc 1 2”,对,oracle,操作(续),其它,操作,set sql“insert into$TableName”,append sql“(field1,.)”,.,If catch$DBSQL$DBHandle$sql errinfo ,puts“some wrong,$errinfo”,$DBCLOSE$DBHandle,return-1,$DBCOMMIT$DBHandle,注意catch的应用。在实际应用中如果有大量数据操作,可以分批提交以加快速度。,预编译,操作,$DBSQL$DBHandle update bms_subscription set bms_user_password,=:user_password where bms_user_name=:user_name -parseonly,orabindexec$DBHandle:user_password$user_password,:user_name$user_name,ktcl,文件,ktcl,文件实际上是,html,文件,里面可以加入,标签:,使用明细查询结果,proc days_of_month year month,if info exists QUERY(bill_type);#从上一个页面传来参数,注意用法!,set bill_type string trim$QUERY(bill_type),;#变量在整个文件有效,else,set:error_msg,参数,bill_type,未找到!,:,kap:loadpage error.ktcl,puts“”,;#,tcl,的输出是标准的,html,文本,由浏览器显示,return,一些编程建议,代码说明,文件头:摘要、版权、版本信息、其它(包定义),过程头:摘要、参数、结果,缩进,最好用4个空格缩进;如果是单行折返(即用连接的两行,后续行)缩进8个空格,关于,最好在行末;在控制结构里对最好存在,哪怕里面只有一行,if$tcl_platform(platform)=“unix”return,就不如,if$tcl_platform(platform)=“unix”,return,清晰的表达式,if$x 22&$y 22)&($y=47),过程必须有,return,后附,还有什么问题?,一个程序例子,程序,inter_checkdetail.tcl,是,在联通写的程序。我之所以把它挑出来,是因为里面用了大部分常用,tcl,命令。,程序的功能是在,detail,文件中挑出用户名中不带指定域名的,detail,输出到新文件。,如:,inter_checkdetail.tcl“gric GRIC fcc ipass”outfile.txt detail/*,把,detail,目录中的所有文件中,ai-Service-User,里不带,gric GRIC,的,detail,数据提取出来。,
展开阅读全文