对于很多魔兽世界私发服新手gm来说wowoemu的tcl语言应该的是比较陌生的,因为大多数对魔兽世界私发服初级修改当中基本上是用不到这方面的知识的。只有我们在需要对服务器进行大规模的深层次修改时才会用到,并且还是非用不可。作为一个魔兽gm早晚有一天我们是需要用到这方面技术的,大家仔细观察一定都能够发现目前市场那那些真正赚钱的服务器基本上全部都是经过深层次修改的版本。
WowEmu使用的TCL语言的一些学习资料
TCL语言
Tcltick的构成
-------
Tcl是一种很通用的脚本语言,它几乎在所有的平台上都可以解释运行,功能强大。是toolcommandlanguage的缩写,发音为"tickle”,实际上包含了两个部分:一个语言和一个库。
首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。它有一个简单的语法和很强可扩充性,Tcl可以创建新的过程以增强其内建命令的能力。
其次,Tcl是一个库包,可以被嵌入应用程序,Tcl的库包含了一个分析器、用于执行内建命令的例程和可以使你扩充(定义新的过程)的库函数。应用程序可以产生Tcl命令并执行,命令可以由用户产生,也可以从用户接口的一个输入中读取(按钮或菜单等)。但Tcl库收到命令后将它分解并执行内建的命令,经常会产生递归的调用。
在下面的清单中,将会发现第一个很常见的示例程序,它是用Tcl实现的。这是一个完整的脚本:第一行命令调用tclsh环境,第二行命令执行实际工作。用您所选择的文本编辑器创建该脚本,输入chmod+xhello.tcl使之成为可执行文件,然后执行它以测试您这件“作品”。
~/tcltk$cathello.tcl
#!/usr/bin/tclsh
putsstdout{HelloWorld!}
~/tcltk$./hello.tcl
HelloWorld!
Tcl和Tk是解释型的、可扩展脚本语言。与BSD许可证十分相似,该许可证允许在任何情况下自由使用该软件,只要在所有副本中保留该版权并且在任何分发中一字不差地传递通告。这个许可证条款使Tcl/Tk成为自由软件。
Tcl/Tk是一种解释型环境。可以通过添加预编译的C函数来扩展Tcl解释器,可从Tcl环境内部调用Tcl解释器。可以为特定目的或一般的以及广泛使用的而定制这些扩展。我们将在教程的后面看一些扩展并着重看一下第一个扩展—非常流行的Expect。
在接下来的几屏中,将回顾Tcl语言的一些主要特性,从元字符和全局变量到运算符、数学函数以及核心命令。毕竟,这些命令使Tcl/Tk成为有特色的,逐步发展的语言。请记住,在本教程中没有篇幅涉及每条命令。这里只突出一部分,以后您可以更进一步了解Tcl/Tk。
#!/usr/bin/tclsh
#filenamehello2.tcl
#Thisprogramcodeshows
#metacharacterusage
putsstdout"HelloWorld!\a"
putsstdout{HelloWorld!\a}
setPints6
setDays7
putsstdout"Theanswertotheuniverseis[eval$Pints*$Days]!\n"
***
~/tcltk$./hello2.tcl
HelloWorld!
HelloWorld!\a
Theanswertoeverythingis42!
Tcl元字符
元字符是在Tcl/Tk环境的上下文中有特殊含意的字符或字符对,它们包括分组语句、封装字符串、终止语句以及其它,如下表所示。左边列出的代码中演示了一些元字符。要注意的一个特殊特性是,当使用花括号(防止替代和扩展)代替双引号时,输出中的差异。
#!/usr/bin/tclsh
#filenamehello2.tcl
#Thisprogramcodeshows
#metacharacterusage
putsstdout"HelloWorld!\a"
putsstdout{HelloWorld!\a}
setPints6
setDays7
putsstdout"Theanswertotheuniverseis[eval$Pints*$Days]!\n"
***
~/tcltk$./hello2.tcl
HelloWorld!
HelloWorld!\a
Theanswertoeverythingis42!
字符用作
#注释
;或newline语句分隔符
Name变量(区分大小写)
Name(idx)数组变量
Name(jkl...)多维数组
"string"带替换的引用
{string}不带替换的引用
[string]命令替换
\char反斜杠替代
\行继续(在行尾)
本文来自织梦
TCL语言(二)
Tcl全局变量和反斜杠替代
#!/usr/bin/tclsh
#
#Demonstrateglobalvariables
#andbackslashsubstitution
if{$argc>=1}{
setN1
foreachArg$argv{
putsstdout"$N:$Arg\n"
setN[expr$N+1]
if{$Arg=="ring"}{
putsstdout"\a"
}
}
}else{
putsstdout"$argv0onXDisplay$env(DISPLAY)\n"
}
***
~/tcltk$./hello3.tcl
./hello3.tclonXDisplay:0.0
~/tcltk$./hello3.tclring
1:ring
Tcl全局变量和反斜杠替代
当Tcl/Tk脚本开始运行时,存在几个全局变量(如果在当前环境中为非空,则是预先定义的)。这些变量允许如下对操作系统进行访问:argc是对脚本自变量的计数,而不是对调用的名称进行计数。argv是自变量的列表(不是数组)。argv0是调用的文件名(可以是符号链接)。env是根据当前外壳的环境变量名建立下标的数组。errorCode存储有关最近的Tcl错误信息,errorInfo包含对这同一个错误事件的堆栈跟踪。该列表还有另外12个tcl_xxx变量,从tcl_interactive到tcl_version。可以在Tcl/TkinaNutshell中找到好的总结,(有关更多信息,请参阅本教程末尾的“参考资料”)。本文来自织梦
在左边的样本代码中,使用了其中几个变量以及(又一次)使用了一些反斜杠引用的字符(\n和\a)。\char允许替代非打印ASCII字符。这对于UNIX下的许多脚本语言和外壳环境都是常见的。如表中说明的那样,对于没有定义替代的反斜杠引用的字符只被简单地回送到输出。
\字符替代
\a响铃
\b退格
\f换页
\n或\newline新行
\r回车
\t水平制表
\v垂直制表
\space("\")空格
\ddd八进制值
\xddd...十六进制值
\c回显‘c’
\反斜
TCL语言(三)
Tcl运算符和数学函数
~/tcltk$catmaths.tcl
#!/usr/bin/tclsh
#
#Demonstrateoperatorsand
#mathfunctions
setPI[expr2*asin(1.0)]
if{$argc==3}{
setX[lindex$argv0]
setY[lindex$argv1]
setRad[lindex$argv2]
setDist[exprsqrt(($X*$X)+($Y*$Y))]
setCir[expr2*$PI*$Rad]
setArea[expr$PI*$Rad*$Rad]
putsstdout"Distance=$Dist"
putsstdout"Circumference=$Cir"
putsstdout"Area=$Area"
}else{
putsstdout"Wrongargumentcount!"
putsstdout"NeedsXYandRadius"
}
********
~/tcltk$./maths.tcl345
Distance=5.0
Circumference=31.4159265359
Area=78.5398163397
Tcl支持一组标准的运算符和数学函数。这些运算符包括算术、位和逻辑运算符,可以通过expr命令使用常规的运算符优先次序规则进行求值。另外,考虑到Tcl的实质是面向字符串的脚本语言,所以对一些数学函数进行了合理的补充:
三角函数包括cos(x)、acos(x)、cosh(x)、sin(x)、asin(x)、sinh(x)、tan(x)、atan(x)、atan2(yx)、tanh(x)和hypot(xy)。与这些函数相关的单位是蝗。
Log函数是exp(x)、log(x)和log10(x)。
算术函数是ceil(x)、floor(x)、fmod(xy)、pow(xy)、abs(x)、int(x)、double(x)和round(x)。
rand()和srand(x)是处理随机数的函数。
左边这个示例使用了其中一些运算符和函数来计算指定点到原点之间的距离,并返回给定半径的圆的周长和面积。另外,在这个示例中,使用列表下标(lindex)命令来访问$argv的个别元素。
TCL语言(四)
Tcl中的循环和分支
...
#
#parsecommandlineswitches
setOptimize0
setVerbose0
foreachArg$argv{
switch-glob--$Arg{
-o*{setOptimize1}
-v*{setVerbose1}
default{
error"Unknown$Arg"
}
}
}
setLineCount0
while{[getsstdinLine]>=0}{
#toconfuseVannaWhite...
Remove_Vowels$Line$Optimize$Verbose
incrLineCount
}
returnLineCount
...
Tcl中的循环命令是while、for和foreach。条件(转移)命令是if/then/else/elsif和switch。上述命令的限定语句是break、continue、return和error。最后,catch命令提供了错误处理能力。
if/then/else/elsif已在前面几屏中演示过。在正式语法中会用到then,但通常会省略掉它。
在左边这个示例中,foreach结构给switch命令提供命令行自变量。当处理自变量时(注意:不正确的输入会终止脚本,因为还没有实现处理错误的catch),while循环通过为每一行调用过程并同时对行计数器加1来处理输入。代码段结束时,返回处理的行数。
TCL语言(五)
Tcl字符串和模式匹配
~/tcltk$tclsh
%setPhrase"helloworld!"
helloworld!
%stringtoupper$Phrase
HELLOWORLD!
%stringtotitle$Phrase
Helloworld!
%stringmatchello$Phrase
0
%stringmatch*ello*$Phrase
1
%stringlength$Phrase
14
%appendPhrase"Nicedayeh?"
helloworld!
Nicedayeh?
%stringtoupper$Phrase
HELLOWORLD!
NICEDAYEH?
%stringwordend$Phrase7
12
字符串是Tcl中的基本数据类型。string命令实际上是一组命令,这些命令都是属于string的。在使用中,正如在左边的示例中所看到,string读取的方式非常象来自OOP编程特定对象方法的应用程序。
表示信息的string命令是length和bytelength(可以有所不同,这取决于字符集)。返回布尔值(1或0)的比较是compare、equal和match。这里的模式匹配是由“文件名替换”(简单类型的匹配通常与外壳操作相关)完成。还可以通过独特的regex和regsub命令来使用“高级正规表达式”。
在Tcl中执行index、last、first、wordend和wordstart命令可以实现下标功能。字符串修改是由tolower、toupper、totitle、trim、trimleft、trimright、replace和map来处理的。后者需要预先定义一个字符映射表。用range抽取子字符串,用repeat多次输出字符串。
可以使用append命令,将文本添加到现有变量中。通过使用与C语言的printf命令相同的样式和约定,format命令可用来生成输出字符串。scan对字符串进行解析并将值赋值给变量。最后,从Tcl8.0开始,用binaryformat和binaryscan命令添加了将二进制数据作为字符串处理的功能(因而能够处理空字符,而不会失败)。
TCL语言(六)
Tcl列表
~/tcltk$tclsh
%setc1{BobCarol}
BobCarol
%setc2[listTedAlice]
TedAlice
%setParty1[list$c1$c2]
{BobCarol}{TedAlice}
%setParty2[concat$c1$c2]
BobCarolTedAlice
%linsert$Party11Richard
{BobCarol}Richard{TedAlice}本文来自织梦
%
列表在Tcl中有两个主要用途。我们已经在通过foreach命令(在Tcl中的循环和分支中找到)处理命令行自变量的环境中看到第一个用途。第二个用途是动态地构建Tcl命令的元素,可以在本教程后面看到使用eval命令来执行这种用途。
list命令接受它的所有自变量并将它们返回在一个列表环境中。自变量可以是值或变量。在左边这个示例中,可以手工创建列表,或可将其它列表视作自变量来使用列表(从而保存第一个“Party”的两对方向)。或者,concat命令用于将两个或多个列表合并到顶级项的单个实体,返回第二个更有趣的“Party”。
其它一些有用的列表命令及其语法是:
llength$List—返回顶级项的计数结果。
lindex$Listn—返回已建立下标的项,从0开始计数。
lrange$Listij—返回列表元素的范围。
lappend$Listitem...—将项附加到列表。
linsert$Listnitem...—在列表中的指dingwei置上插入一项或多项,向下移列表中的其它项。
其余列表命令还包括lreplace、lsearch和lsort。split命令将字符串作为输入并生成经过正确解析的列表,并且在指定的字符处断开字符串。join执行相反操作,接受列表元素并将它们串在一起,用joinstring分隔它们。
TCL语言(六)
Tcl数组
~/tcltk$tclsh
%setPeople(friend)Tom
Tom
%setPeople(spouse)Marcia
Marcia
%setPeople(boss)Jack
Jack
%arraynamesPeople
friendbossspouse
%setPerson$People(friend)
Tom
%arraygetPeople
friendTombossJackspouseMarcia
%setPeople(friend)[concat$People(friend)Bob]
TomBob
%setPerson$People(friend)
TomBob
%
理解Tcl数组的捷径是,将它们视作与Perl散列相同的东西。Tcl数组不是用数字建立下标的线性数据结构,除非选择对数据强加那种解释。尽管带空格的字符串需要用引号括起或需要一个变量引用,但下标(或键)可以是任何字符串。
正如一般的变量一样,使用set命令初始化数组,如左边所示。圆括号内是给出的下标部分。请注意,圆括号不象花括号或双引号那样提供分组。一旦初始化为数组,就不能将变量作为单一变量来访问。如左边列表底部所示,数组元素也可以是列表。
更多Tcl数组
array命令是一种多用途工具,很象string。arrayexists命令用于测试变量是否作为数组存在,arrayget用于将数组转换成列表格式,arrayset用于将列表转换为数组,arraynames用于返回下标列表,arraysize用于返回对下标进行计数的结果。搜索整个数组有它自己的一组四个命令:arraystartseach、arrayanymore、arraynextelement和arraydonesearch。
虽然设计之初Tcl数组是一维的,但有一个模拟多维结构的好方法。因为下标是任意字符串,所以二维数组可以声明如下:
seti1;setj10
setarray($i$j)3.14159
incr$j
setarray($i$j)2.71828
这些数组键实际上分别只是字符串“110”和“111”,但对访问数据来说,谁知道这之间的差异?
TCL语言(七)
Tcl过程
#!/usr/bin/tclsh
#
#Demonstrateproceduresand
#globalscopingbriefly
setPI[expr2*asin(1.0)]
proccircum{
globalPI
return[expr2.0*$rad*$PI]
}
procc_area{
globalPI
return[expr$rad*$rad*$PI]
}
setrad3
putsstdout"Areaofcircleofradius$radis[c_area$rad]\nthecircumferenceis[circum$rad].\n"
*********
~/tcltk$./protest.tcl
Areaofcircleofradius3is28.2743338823
thecircumferenceis18.8495559215.
proc命令定义Tcl过程。一旦定义后,就可以象内置的Tcl命令那样调用或使用它。另外,可以用缺省值定义这些参数;例如,将左边的定义更改为读取procc_area{{rad1}}。这将调用没有参数的c_area过程,并返回单位圆的面积。本文来自织梦
所使用的rename命令正如它的字面含意一样,为现有命令或过程提供新名称。使用rename有两个明显的原因。第一个原因是,通过重命名原有过程,然后用相同名称的过程替换它,来给现有命令添加功能。过程可以调用原过程,必要时可以添加一些需要的功能。使用rename的第二个原因是,映射一个不存在的命令,例如,象renameexec{};一样,可以防止用户执行外部命令。
变量作用域规则
作用域规则描述了过程和变量名以及值在程序的不同层次上的可见性。例如,在脚本的最外层定义的变量是全局变量。缺省情况下,全局变量是不可见的,在过程内部也不可用它们的值。这允许过程的编写者自由地定义变量名并赋值,而不必担心覆盖对于局部作用域上未知的重要变量。要使全局变量在过程内部变得可见,必须将它声明为在过程内,就象在上一屏的示例中,对PI使用global命令那样。
upvar命令提供将局部变量与另一个作用域中变量的值相关联的设施。这允许根据名称将变量调用进过程,这对于当过程需要可以修改在另一个作用域的值而不仅仅使用它时,就显得非常方便。这个命令语法是upvarlevel$VarNameLocalVar,其中level是到当前作用域之外的步骤数。“#0”表示全局作用域这一层。
TCL语言(八)
Tcl中的数据结构
#!/usr/bin/tclsh
#
#DemonstrateDataStructures
#usingproceduralwrappers
procUserAdd{AcctrNameeMailphone}{
globaluData
if{[infoexistsuData($Acctrname)]}{
return1
}
setuData($Acctrname)$rName
setuData($Acctemail)$eMail
setuData($Acctphone)$phone
return0
}
putsstdout[[email protected]]
putsstdout[[email protected]]
putsstdout[[email protected]]
******
~/tcltk$./datas.tcl
0
0
1
除简单的多维数组以外,通常建议用已专门用于过程接口的数组来实现Tcl数据结构。从结构的使用者角度来看,虽然这种设计隐藏了具体实现细节,但提供了执行重要的错误检查能力。
左边这个示例中,在将uData声明为全局变量后,代码执行检查,以查看帐户是否已经不存在。如果存在,则过程返回(非零)错误消息。这个返回可以用于切换到生成错误文本输出。对于本例,我们简单地提供三个连续输入,其中包括一次重复输入。这会产生如示例底部所示的输出,“1”表示由于一个重复的帐户名称而引起的一个错误返回,这是我们有意这样做的。
其它可能的数据结构包括数组列表、已链接或双重链接的数组或其中的各种排列。因为Tcl8.0所具有的列表重实现提供了不变的访问次数,所以数组列表结构相当有效。
TCL语言(九)
路径和文件
~/tcltk$tclsh
%fileexistshello3.tcl
1
%fileexecutabletestit
0
%filepathtype./hello3.tcl
relative
%setdir1home
home
%setdir2brian
brian
%setdir3tcltk
tcltk
%filejoin/$dir1dir2dir3
/home/dir2/dir3
%filedeletetestit~
%
文件和路径操作是跨平台环境中具有挑战性的问题。对于主机OS,Tcl使用UNIX路径名(缺省情况下,用‘/’字符分隔)和本机路径名结构。即使当程序内的数据构造正确时,也很难确保用户输入与系统需求匹配。filejoin命令用于将UNIX格式转换成本机路径名。其它路径字符串命令包括filesplit、dirname、fileextension、nativename、pathtype和tail。
在它扮演的“工具控制语言”角色中,Tcl有许许多多种内部文件测试和操作功能。每条命令都以file开始,正如fileexistsname中一样。其它测试命令(它们都返回布尔值)包括executable、isdirectory、isfile、owned、readable和writable。
文件信息和操作(再提醒您一次,所有都是以file开始)是通过atime、attributes、copy、delete、lstat、mkdir、mtime、readlink、rename、rootname、size、stat和type来完成。请注意,在Windows或Mac环境中运行一些文件信息命令时,可能会返回未定义的数据,因为例如在那些文件系统中没有表示索引节点和符号(和硬)链接数据。
使用file...命令而不使用通过exec的本机命令的好处在于,前者会提供一个可移植接口。TCL语言(十)
Tcl进程和文件I/O
~/tcltk$tclsh
%nslookuporbdesigns.com
Server:192.168.1.3
Address:192.168.1.3#53
Name:orbdesigns.com
Address:64.81.69.163
%setd[date]
SunMar2513:51:59PST2001
%putsstdout$d
%setd[execdate]
SunMar2513:52:19PST2001
%putsstdout$d
SunMar2513:52:19PST2001
******
%if[catch{openfoor}Chan]{
putsstdout"SorryDave...\n"
}
%gets$Chan
One
%gets$Chan
Two
%eof$Chan
0
%close$Chan
%
exec命令用于显式地执行外部命令。在Linux下,当Tcl处于交互方式时,可以直接运行大多数外部命令,如左边示例所示。用exec运行时,会将程序的stdout输出返回到Tcl,而不是返回到屏幕,这允许将数据赋值给变量。当程序在后台启动时,立即返回的值是程序的PID。exec程序可以充分利用UNIX环境中的I/O重定向和管道。
其它进程命令有exit(终止正在运行的Tcl脚本)和pid(返回当前或指定进程的PID),对于出于各种目的的情况,这非常便利。Tcl不合并任何本机进程控制命令,但可以将exec命令与PID数据一起使用来实现许多任务。
文件操纵使用下列命令:open、close、gets、puts、read、tell、seek、eof和flush。如左边所示,在文件打开命令期间catch命令对错误检查是有用的。当在遇到新的一行字符之前需要打印程序输出时,如在用户数据提示符中,使用flush来写输出缓冲区。
另外一个功能(在受支持的环境中)是以打开文件的方式打开管道的能力。例如,用setChannel[open"|sortfoobar"r]打开管道通道后,第一个gets的输出将是“Eight”(文件数据“One”到“Ten”的输出在10个单独的行上按字母顺序排列)。
将eval用于动态脚本
~/tcltk$catinput01.txt
1+2
4+5
7-9
~/tcltk$tclsh
%setInFile[openinput01.txtr]
file3
%while{[gets$InFileOp]>=0}{
setOperation"expr$Op"
setResult[eval$Operation]
putsstdout"$Op=$Result\n"
}
1+2=3
4+5=9
7-9=-2
%
在这个示例中,您可以感到eval命令的强大功能。在正常情况下,Tcl解释器以一遍方式(one-pass)操作:它首先对输入的命令行(可能延伸在几个物理行上)进行解析,并执行任何替代。然后开始执行,除非找到不正常或残缺命令。eval允许第二遍方式(secondpass)(或许更精确地讲,是预通过(pre-pass))。因而,可以先动态构造Tcl命令,然后进行解析并执行它。
在左边的列表中,输入文件由三行组成,每行都显示了一种算术运算。调用tclsh后,文件以只读方式打开并与$InFile变量相关联。while循环每次将一行读入到$Op中。然后,通过预先计划将expr映射到$Op变量来构造整个Tcl命令。然后,扩展,求值,从而分配结果。最后,在stdout上显示每步操作和结果。
虽然该样本演示了相对琐细的eval应用程序,但从概念上讲,可以根据已知语法的输入文件的输入,很容易地将它扩展为动态文件和/或目录处理,或扩展为对文件类型、许可权、访问时间或任何种类的可测试元素的基本操作。
以上就是一为原创给大家分享的魔兽世界私发服游戏高级技术攻略之wowoemu使用的tcl语言学习资料全部内容,以后大家在服务器修改过程中如果需要用到这方面的知识,可以根据文章中提供的方法进行操作,这篇魔兽攻略算是目前市场上比较全面的wowomu使用tcl学习资料了。
WowEmu使用的TCL语言的一些学习资料
TCL语言
Tcltick的构成
-------
Tcl是一种很通用的脚本语言,它几乎在所有的平台上都可以解释运行,功能强大。是toolcommandlanguage的缩写,发音为"tickle”,实际上包含了两个部分:一个语言和一个库。
首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。它有一个简单的语法和很强可扩充性,Tcl可以创建新的过程以增强其内建命令的能力。
其次,Tcl是一个库包,可以被嵌入应用程序,Tcl的库包含了一个分析器、用于执行内建命令的例程和可以使你扩充(定义新的过程)的库函数。应用程序可以产生Tcl命令并执行,命令可以由用户产生,也可以从用户接口的一个输入中读取(按钮或菜单等)。但Tcl库收到命令后将它分解并执行内建的命令,经常会产生递归的调用。
在下面的清单中,将会发现第一个很常见的示例程序,它是用Tcl实现的。这是一个完整的脚本:第一行命令调用tclsh环境,第二行命令执行实际工作。用您所选择的文本编辑器创建该脚本,输入chmod+xhello.tcl使之成为可执行文件,然后执行它以测试您这件“作品”。
~/tcltk$cathello.tcl
#!/usr/bin/tclsh
putsstdout{HelloWorld!}
~/tcltk$./hello.tcl
HelloWorld!
Tcl和Tk是解释型的、可扩展脚本语言。与BSD许可证十分相似,该许可证允许在任何情况下自由使用该软件,只要在所有副本中保留该版权并且在任何分发中一字不差地传递通告。这个许可证条款使Tcl/Tk成为自由软件。
Tcl/Tk是一种解释型环境。可以通过添加预编译的C函数来扩展Tcl解释器,可从Tcl环境内部调用Tcl解释器。可以为特定目的或一般的以及广泛使用的而定制这些扩展。我们将在教程的后面看一些扩展并着重看一下第一个扩展—非常流行的Expect。
在接下来的几屏中,将回顾Tcl语言的一些主要特性,从元字符和全局变量到运算符、数学函数以及核心命令。毕竟,这些命令使Tcl/Tk成为有特色的,逐步发展的语言。请记住,在本教程中没有篇幅涉及每条命令。这里只突出一部分,以后您可以更进一步了解Tcl/Tk。
#!/usr/bin/tclsh
#filenamehello2.tcl
#Thisprogramcodeshows
#metacharacterusage
putsstdout"HelloWorld!\a"
putsstdout{HelloWorld!\a}
setPints6
setDays7
putsstdout"Theanswertotheuniverseis[eval$Pints*$Days]!\n"
***
~/tcltk$./hello2.tcl
HelloWorld!
HelloWorld!\a
Theanswertoeverythingis42!
Tcl元字符
元字符是在Tcl/Tk环境的上下文中有特殊含意的字符或字符对,它们包括分组语句、封装字符串、终止语句以及其它,如下表所示。左边列出的代码中演示了一些元字符。要注意的一个特殊特性是,当使用花括号(防止替代和扩展)代替双引号时,输出中的差异。
#!/usr/bin/tclsh
#filenamehello2.tcl
#Thisprogramcodeshows
#metacharacterusage
putsstdout"HelloWorld!\a"
putsstdout{HelloWorld!\a}
setPints6
setDays7
putsstdout"Theanswertotheuniverseis[eval$Pints*$Days]!\n"
***
~/tcltk$./hello2.tcl
HelloWorld!
HelloWorld!\a
Theanswertoeverythingis42!
字符用作
#注释
;或newline语句分隔符
Name变量(区分大小写)
Name(idx)数组变量
Name(jkl...)多维数组
"string"带替换的引用
{string}不带替换的引用
[string]命令替换
\char反斜杠替代
\行继续(在行尾)
本文来自织梦
TCL语言(二)
Tcl全局变量和反斜杠替代
#!/usr/bin/tclsh
#
#Demonstrateglobalvariables
#andbackslashsubstitution
if{$argc>=1}{
setN1
foreachArg$argv{
putsstdout"$N:$Arg\n"
setN[expr$N+1]
if{$Arg=="ring"}{
putsstdout"\a"
}
}
}else{
putsstdout"$argv0onXDisplay$env(DISPLAY)\n"
}
***
~/tcltk$./hello3.tcl
./hello3.tclonXDisplay:0.0
~/tcltk$./hello3.tclring
1:ring
Tcl全局变量和反斜杠替代
当Tcl/Tk脚本开始运行时,存在几个全局变量(如果在当前环境中为非空,则是预先定义的)。这些变量允许如下对操作系统进行访问:argc是对脚本自变量的计数,而不是对调用的名称进行计数。argv是自变量的列表(不是数组)。argv0是调用的文件名(可以是符号链接)。env是根据当前外壳的环境变量名建立下标的数组。errorCode存储有关最近的Tcl错误信息,errorInfo包含对这同一个错误事件的堆栈跟踪。该列表还有另外12个tcl_xxx变量,从tcl_interactive到tcl_version。可以在Tcl/TkinaNutshell中找到好的总结,(有关更多信息,请参阅本教程末尾的“参考资料”)。本文来自织梦
在左边的样本代码中,使用了其中几个变量以及(又一次)使用了一些反斜杠引用的字符(\n和\a)。\char允许替代非打印ASCII字符。这对于UNIX下的许多脚本语言和外壳环境都是常见的。如表中说明的那样,对于没有定义替代的反斜杠引用的字符只被简单地回送到输出。
\字符替代
\a响铃
\b退格
\f换页
\n或\newline新行
\r回车
\t水平制表
\v垂直制表
\space("\")空格
\ddd八进制值
\xddd...十六进制值
\c回显‘c’
\反斜
TCL语言(三)
Tcl运算符和数学函数
~/tcltk$catmaths.tcl
#!/usr/bin/tclsh
#
#Demonstrateoperatorsand
#mathfunctions
setPI[expr2*asin(1.0)]
if{$argc==3}{
setX[lindex$argv0]
setY[lindex$argv1]
setRad[lindex$argv2]
setDist[exprsqrt(($X*$X)+($Y*$Y))]
setCir[expr2*$PI*$Rad]
setArea[expr$PI*$Rad*$Rad]
putsstdout"Distance=$Dist"
putsstdout"Circumference=$Cir"
putsstdout"Area=$Area"
}else{
putsstdout"Wrongargumentcount!"
putsstdout"NeedsXYandRadius"
}
********
~/tcltk$./maths.tcl345
Distance=5.0
Circumference=31.4159265359
Area=78.5398163397
Tcl支持一组标准的运算符和数学函数。这些运算符包括算术、位和逻辑运算符,可以通过expr命令使用常规的运算符优先次序规则进行求值。另外,考虑到Tcl的实质是面向字符串的脚本语言,所以对一些数学函数进行了合理的补充:
三角函数包括cos(x)、acos(x)、cosh(x)、sin(x)、asin(x)、sinh(x)、tan(x)、atan(x)、atan2(yx)、tanh(x)和hypot(xy)。与这些函数相关的单位是蝗。
Log函数是exp(x)、log(x)和log10(x)。
算术函数是ceil(x)、floor(x)、fmod(xy)、pow(xy)、abs(x)、int(x)、double(x)和round(x)。
rand()和srand(x)是处理随机数的函数。
左边这个示例使用了其中一些运算符和函数来计算指定点到原点之间的距离,并返回给定半径的圆的周长和面积。另外,在这个示例中,使用列表下标(lindex)命令来访问$argv的个别元素。
TCL语言(四)
Tcl中的循环和分支
...
#
#parsecommandlineswitches
setOptimize0
setVerbose0
foreachArg$argv{
switch-glob--$Arg{
-o*{setOptimize1}
-v*{setVerbose1}
default{
error"Unknown$Arg"
}
}
}
setLineCount0
while{[getsstdinLine]>=0}{
#toconfuseVannaWhite...
Remove_Vowels$Line$Optimize$Verbose
incrLineCount
}
returnLineCount
...
Tcl中的循环命令是while、for和foreach。条件(转移)命令是if/then/else/elsif和switch。上述命令的限定语句是break、continue、return和error。最后,catch命令提供了错误处理能力。
if/then/else/elsif已在前面几屏中演示过。在正式语法中会用到then,但通常会省略掉它。
在左边这个示例中,foreach结构给switch命令提供命令行自变量。当处理自变量时(注意:不正确的输入会终止脚本,因为还没有实现处理错误的catch),while循环通过为每一行调用过程并同时对行计数器加1来处理输入。代码段结束时,返回处理的行数。
TCL语言(五)
Tcl字符串和模式匹配
~/tcltk$tclsh
%setPhrase"helloworld!"
helloworld!
%stringtoupper$Phrase
HELLOWORLD!
%stringtotitle$Phrase
Helloworld!
%stringmatchello$Phrase
0
%stringmatch*ello*$Phrase
1
%stringlength$Phrase
14
%appendPhrase"Nicedayeh?"
helloworld!
Nicedayeh?
%stringtoupper$Phrase
HELLOWORLD!
NICEDAYEH?
%stringwordend$Phrase7
12
字符串是Tcl中的基本数据类型。string命令实际上是一组命令,这些命令都是属于string的。在使用中,正如在左边的示例中所看到,string读取的方式非常象来自OOP编程特定对象方法的应用程序。
表示信息的string命令是length和bytelength(可以有所不同,这取决于字符集)。返回布尔值(1或0)的比较是compare、equal和match。这里的模式匹配是由“文件名替换”(简单类型的匹配通常与外壳操作相关)完成。还可以通过独特的regex和regsub命令来使用“高级正规表达式”。
在Tcl中执行index、last、first、wordend和wordstart命令可以实现下标功能。字符串修改是由tolower、toupper、totitle、trim、trimleft、trimright、replace和map来处理的。后者需要预先定义一个字符映射表。用range抽取子字符串,用repeat多次输出字符串。
可以使用append命令,将文本添加到现有变量中。通过使用与C语言的printf命令相同的样式和约定,format命令可用来生成输出字符串。scan对字符串进行解析并将值赋值给变量。最后,从Tcl8.0开始,用binaryformat和binaryscan命令添加了将二进制数据作为字符串处理的功能(因而能够处理空字符,而不会失败)。
TCL语言(六)
Tcl列表
~/tcltk$tclsh
%setc1{BobCarol}
BobCarol
%setc2[listTedAlice]
TedAlice
%setParty1[list$c1$c2]
{BobCarol}{TedAlice}
%setParty2[concat$c1$c2]
BobCarolTedAlice
%linsert$Party11Richard
{BobCarol}Richard{TedAlice}本文来自织梦
%
列表在Tcl中有两个主要用途。我们已经在通过foreach命令(在Tcl中的循环和分支中找到)处理命令行自变量的环境中看到第一个用途。第二个用途是动态地构建Tcl命令的元素,可以在本教程后面看到使用eval命令来执行这种用途。
list命令接受它的所有自变量并将它们返回在一个列表环境中。自变量可以是值或变量。在左边这个示例中,可以手工创建列表,或可将其它列表视作自变量来使用列表(从而保存第一个“Party”的两对方向)。或者,concat命令用于将两个或多个列表合并到顶级项的单个实体,返回第二个更有趣的“Party”。
其它一些有用的列表命令及其语法是:
llength$List—返回顶级项的计数结果。
lindex$Listn—返回已建立下标的项,从0开始计数。
lrange$Listij—返回列表元素的范围。
lappend$Listitem...—将项附加到列表。
linsert$Listnitem...—在列表中的指dingwei置上插入一项或多项,向下移列表中的其它项。
其余列表命令还包括lreplace、lsearch和lsort。split命令将字符串作为输入并生成经过正确解析的列表,并且在指定的字符处断开字符串。join执行相反操作,接受列表元素并将它们串在一起,用joinstring分隔它们。
TCL语言(六)
Tcl数组
~/tcltk$tclsh
%setPeople(friend)Tom
Tom
%setPeople(spouse)Marcia
Marcia
%setPeople(boss)Jack
Jack
%arraynamesPeople
friendbossspouse
%setPerson$People(friend)
Tom
%arraygetPeople
friendTombossJackspouseMarcia
%setPeople(friend)[concat$People(friend)Bob]
TomBob
%setPerson$People(friend)
TomBob
%
理解Tcl数组的捷径是,将它们视作与Perl散列相同的东西。Tcl数组不是用数字建立下标的线性数据结构,除非选择对数据强加那种解释。尽管带空格的字符串需要用引号括起或需要一个变量引用,但下标(或键)可以是任何字符串。
正如一般的变量一样,使用set命令初始化数组,如左边所示。圆括号内是给出的下标部分。请注意,圆括号不象花括号或双引号那样提供分组。一旦初始化为数组,就不能将变量作为单一变量来访问。如左边列表底部所示,数组元素也可以是列表。
更多Tcl数组
array命令是一种多用途工具,很象string。arrayexists命令用于测试变量是否作为数组存在,arrayget用于将数组转换成列表格式,arrayset用于将列表转换为数组,arraynames用于返回下标列表,arraysize用于返回对下标进行计数的结果。搜索整个数组有它自己的一组四个命令:arraystartseach、arrayanymore、arraynextelement和arraydonesearch。
虽然设计之初Tcl数组是一维的,但有一个模拟多维结构的好方法。因为下标是任意字符串,所以二维数组可以声明如下:
seti1;setj10
setarray($i$j)3.14159
incr$j
setarray($i$j)2.71828
这些数组键实际上分别只是字符串“110”和“111”,但对访问数据来说,谁知道这之间的差异?
TCL语言(七)
Tcl过程
#!/usr/bin/tclsh
#
#Demonstrateproceduresand
#globalscopingbriefly
setPI[expr2*asin(1.0)]
proccircum{
globalPI
return[expr2.0*$rad*$PI]
}
procc_area{
globalPI
return[expr$rad*$rad*$PI]
}
setrad3
putsstdout"Areaofcircleofradius$radis[c_area$rad]\nthecircumferenceis[circum$rad].\n"
*********
~/tcltk$./protest.tcl
Areaofcircleofradius3is28.2743338823
thecircumferenceis18.8495559215.
proc命令定义Tcl过程。一旦定义后,就可以象内置的Tcl命令那样调用或使用它。另外,可以用缺省值定义这些参数;例如,将左边的定义更改为读取procc_area{{rad1}}。这将调用没有参数的c_area过程,并返回单位圆的面积。本文来自织梦
所使用的rename命令正如它的字面含意一样,为现有命令或过程提供新名称。使用rename有两个明显的原因。第一个原因是,通过重命名原有过程,然后用相同名称的过程替换它,来给现有命令添加功能。过程可以调用原过程,必要时可以添加一些需要的功能。使用rename的第二个原因是,映射一个不存在的命令,例如,象renameexec{};一样,可以防止用户执行外部命令。
变量作用域规则
作用域规则描述了过程和变量名以及值在程序的不同层次上的可见性。例如,在脚本的最外层定义的变量是全局变量。缺省情况下,全局变量是不可见的,在过程内部也不可用它们的值。这允许过程的编写者自由地定义变量名并赋值,而不必担心覆盖对于局部作用域上未知的重要变量。要使全局变量在过程内部变得可见,必须将它声明为在过程内,就象在上一屏的示例中,对PI使用global命令那样。
upvar命令提供将局部变量与另一个作用域中变量的值相关联的设施。这允许根据名称将变量调用进过程,这对于当过程需要可以修改在另一个作用域的值而不仅仅使用它时,就显得非常方便。这个命令语法是upvarlevel$VarNameLocalVar,其中level是到当前作用域之外的步骤数。“#0”表示全局作用域这一层。
TCL语言(八)
Tcl中的数据结构
#!/usr/bin/tclsh
#
#DemonstrateDataStructures
#usingproceduralwrappers
procUserAdd{AcctrNameeMailphone}{
globaluData
if{[infoexistsuData($Acctrname)]}{
return1
}
setuData($Acctrname)$rName
setuData($Acctemail)$eMail
setuData($Acctphone)$phone
return0
}
putsstdout[[email protected]]
putsstdout[[email protected]]
putsstdout[[email protected]]
******
~/tcltk$./datas.tcl
0
0
1
除简单的多维数组以外,通常建议用已专门用于过程接口的数组来实现Tcl数据结构。从结构的使用者角度来看,虽然这种设计隐藏了具体实现细节,但提供了执行重要的错误检查能力。
左边这个示例中,在将uData声明为全局变量后,代码执行检查,以查看帐户是否已经不存在。如果存在,则过程返回(非零)错误消息。这个返回可以用于切换到生成错误文本输出。对于本例,我们简单地提供三个连续输入,其中包括一次重复输入。这会产生如示例底部所示的输出,“1”表示由于一个重复的帐户名称而引起的一个错误返回,这是我们有意这样做的。
其它可能的数据结构包括数组列表、已链接或双重链接的数组或其中的各种排列。因为Tcl8.0所具有的列表重实现提供了不变的访问次数,所以数组列表结构相当有效。
TCL语言(九)
路径和文件
~/tcltk$tclsh
%fileexistshello3.tcl
1
%fileexecutabletestit
0
%filepathtype./hello3.tcl
relative
%setdir1home
home
%setdir2brian
brian
%setdir3tcltk
tcltk
%filejoin/$dir1dir2dir3
/home/dir2/dir3
%filedeletetestit~
%
文件和路径操作是跨平台环境中具有挑战性的问题。对于主机OS,Tcl使用UNIX路径名(缺省情况下,用‘/’字符分隔)和本机路径名结构。即使当程序内的数据构造正确时,也很难确保用户输入与系统需求匹配。filejoin命令用于将UNIX格式转换成本机路径名。其它路径字符串命令包括filesplit、dirname、fileextension、nativename、pathtype和tail。
在它扮演的“工具控制语言”角色中,Tcl有许许多多种内部文件测试和操作功能。每条命令都以file开始,正如fileexistsname中一样。其它测试命令(它们都返回布尔值)包括executable、isdirectory、isfile、owned、readable和writable。
文件信息和操作(再提醒您一次,所有都是以file开始)是通过atime、attributes、copy、delete、lstat、mkdir、mtime、readlink、rename、rootname、size、stat和type来完成。请注意,在Windows或Mac环境中运行一些文件信息命令时,可能会返回未定义的数据,因为例如在那些文件系统中没有表示索引节点和符号(和硬)链接数据。
使用file...命令而不使用通过exec的本机命令的好处在于,前者会提供一个可移植接口。TCL语言(十)
Tcl进程和文件I/O
~/tcltk$tclsh
%nslookuporbdesigns.com
Server:192.168.1.3
Address:192.168.1.3#53
Name:orbdesigns.com
Address:64.81.69.163
%setd[date]
SunMar2513:51:59PST2001
%putsstdout$d
%setd[execdate]
SunMar2513:52:19PST2001
%putsstdout$d
SunMar2513:52:19PST2001
******
%if[catch{openfoor}Chan]{
putsstdout"SorryDave...\n"
}
%gets$Chan
One
%gets$Chan
Two
%eof$Chan
0
%close$Chan
%
exec命令用于显式地执行外部命令。在Linux下,当Tcl处于交互方式时,可以直接运行大多数外部命令,如左边示例所示。用exec运行时,会将程序的stdout输出返回到Tcl,而不是返回到屏幕,这允许将数据赋值给变量。当程序在后台启动时,立即返回的值是程序的PID。exec程序可以充分利用UNIX环境中的I/O重定向和管道。
其它进程命令有exit(终止正在运行的Tcl脚本)和pid(返回当前或指定进程的PID),对于出于各种目的的情况,这非常便利。Tcl不合并任何本机进程控制命令,但可以将exec命令与PID数据一起使用来实现许多任务。
文件操纵使用下列命令:open、close、gets、puts、read、tell、seek、eof和flush。如左边所示,在文件打开命令期间catch命令对错误检查是有用的。当在遇到新的一行字符之前需要打印程序输出时,如在用户数据提示符中,使用flush来写输出缓冲区。
另外一个功能(在受支持的环境中)是以打开文件的方式打开管道的能力。例如,用setChannel[open"|sortfoobar"r]打开管道通道后,第一个gets的输出将是“Eight”(文件数据“One”到“Ten”的输出在10个单独的行上按字母顺序排列)。
将eval用于动态脚本
~/tcltk$catinput01.txt
1+2
4+5
7-9
~/tcltk$tclsh
%setInFile[openinput01.txtr]
file3
%while{[gets$InFileOp]>=0}{
setOperation"expr$Op"
setResult[eval$Operation]
putsstdout"$Op=$Result\n"
}
1+2=3
4+5=9
7-9=-2
%
在这个示例中,您可以感到eval命令的强大功能。在正常情况下,Tcl解释器以一遍方式(one-pass)操作:它首先对输入的命令行(可能延伸在几个物理行上)进行解析,并执行任何替代。然后开始执行,除非找到不正常或残缺命令。eval允许第二遍方式(secondpass)(或许更精确地讲,是预通过(pre-pass))。因而,可以先动态构造Tcl命令,然后进行解析并执行它。
在左边的列表中,输入文件由三行组成,每行都显示了一种算术运算。调用tclsh后,文件以只读方式打开并与$InFile变量相关联。while循环每次将一行读入到$Op中。然后,通过预先计划将expr映射到$Op变量来构造整个Tcl命令。然后,扩展,求值,从而分配结果。最后,在stdout上显示每步操作和结果。
虽然该样本演示了相对琐细的eval应用程序,但从概念上讲,可以根据已知语法的输入文件的输入,很容易地将它扩展为动态文件和/或目录处理,或扩展为对文件类型、许可权、访问时间或任何种类的可测试元素的基本操作。
以上就是一为原创给大家分享的魔兽世界私发服游戏高级技术攻略之wowoemu使用的tcl语言学习资料全部内容,以后大家在服务器修改过程中如果需要用到这方面的知识,可以根据文章中提供的方法进行操作,这篇魔兽攻略算是目前市场上比较全面的wowomu使用tcl学习资料了。

