TCL语言(一)

来源:互联网 发布:linux可执行文件格式 编辑:程序博客网 时间:2024/06/06 04:57

Tcl是一种很通用的脚本语言,它几乎在所有的平台上都可以解释运行,其强大的功能和简单精妙的语法会使你感到由衷的喜悦。


Tcl Overview
这篇文章里包含了几乎 Tcl 的全部。文章的作者是Tcl的缔造者John Ousterhout,对Tcl的诠释非常清楚。

Introduction 简介
Tcl 代表 "tool command language" 发音为 "tickle." 。它实际上包含了两个部分:一个语言和一个库。

首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调试器和shell。它有一个简单的语法和很强可扩充性,Tcl可以创建新的过程以增强其内建命令的能力。

其次,Tcl是一个库包,可以被嵌入应用程序,Tcl的库包含了一个分析器、用于执行内建命令的例程和可以使你扩充(定义新的过程)的库函数。应用程序可以产生Tcl命令并执行,命令可以由用户产生,也可以从用户接口的一个输入中读取(按钮或菜单等)。但Tcl库收到命令后将它分解并执行内建的命令,经常会产生递归的调用。


应用程序使用Tcl作为它的命令语言有三个好处:
1 Tcl提供了标准语法,一旦用户掌握了Tcl就可以很容易的发布命令给基于Tcl的程序。
2 Tcl实现了很多的功能,使你的工作变得很方便。
3 TCl可作为程序间通信的接口。

Tcl Interpreters 解释器

在Tcl的数据结构中的核心是Tcl_Interp.一个解释器包含了一套命令,一组变量和一些用于描述状态的东西。每一个 Tcl命令是在特定的Tcl_Interp中运行的,基于Tcl的应用程序可以同时拥有几个Tcl_Interp。Tcl_Interp是一个轻量级的结构,可以快速的新建和删除。

Tcl Data Types 数据类型

Tcl只支持一种数据结构:字符串(string)。所有的命令,命令的所有的参数,命令的结果,所有的变量都是字符串。请牢记这一点,所有的东西都是字符串。然而字符串的实际解释是依赖于上下文或命令的。它有三种形式:命令(command), 表达式(expresion)和表(list)。下面会讨论细节。

Basic Command Syntax 基本语法

Tcl有类似于shell和lisp的语法,当然也有许多的不同。一条Tcl的命令串包含了一条或多条命令用换行符或分号来隔开,而每一条命令包含了一个域(field)的集合,域使用空白分开的,第一个域是一个命令的名字,其它的是作为参数来传给它。

 

例如:
set a 22 //相当于C中的 a=是一个变量,这条命令分为三个域:1: set 2: a 3: 22。
set使用于设置变量的值的命令,a、20 作为参数来传给它,a使它要操作的变量名,22是要付给的a值。

Tcl的命令名可以使内建的命令也可以是用户建的新命令,在应用程序中用函数Tcl_CreateCommand来创建。所有的参数作为字符串来传递,命令自己会按其所需来解释的参数的。命令的名字必须被打全,但 Tcl解释器找不到一同名的命令时会用 unknown命令来代替。在很多场合下,unknown 会在库目录中搜寻,找到一个的话,会自动生成一个Tcl命令并调用它。unknown经常完成缩略的命令名的执行。但最好不要使用。
Comments 注释和shell很象,第一个字母是"#"的Tcl字符串是注释。

Grouping arguments with double-quotes 用双引号来集群参数

用双引号来集群参数的目的在于使用有空白的参数。
例如:
set a "this string contains whitespace" 如够一个参数一双引号来开始,该参数会一直到下一个双引号
才结束。其中可以有换行符和分号。子替换是在正式运行该调命令之前由分析器作的

Variable substitution with $ 用美元符进行变量替换

说白了就是引用该变量。
如:
set a hello
set b $a // b = "hello" 实际上传给set命令的参数
//是b,"hello"
set c a // b = "a"

Command substitution with brackets 命令子替换(用方括号)

例如:
set a [set b "hello"]
实现执行 set b "hello" 并用其结果来替换源命令中的方括号部分,产生一条新命令
set a "hello" //"hello" 为 set b "hello" 的返//回值,最终的结果是b="hello" a="hello"

当命令的一个子域以方括号开始以方括号结束,表示要进行一个命令子替换。并执行该子命令,用其结果来替换原命令中的方括号部分。方括号中的部分都被视为Tcl命令。

一个复杂一点的例子:
set a xyz[set b "abc"].[set c "def"]
//return xyzabcdef

Backslash substitution 转移符替换转移符时间不可打印字符或由它数意义的字符插入进来。这一概念与C语言中的一样。

\b Backspace (0x8).
\f Form feed (0xc).
\n Newline (0xa).
\r Carriage-return (0xd).
\t Tab (0x9).
\v Vertical tab (0xb).
\{ Left brace (`{").
\} Right brace (`}").
\[ Open bracket (`[").
\] Close bracket (`]").
\$ Dollar sign (`$").
\sp Space (` "): does not terminate argument.
\; Semicolon: does not terminate command.
\" Double-quote.
Grouping arguments with braces 用花扩括号来集群参数

用花扩括号来集群参数与用双引号来集群参数的区别在于:用花扩括号来集群参数其中的三种上述的子替换不被执行。而且可以嵌套。

例如:
set a {xyz a {b c d}}//set收到俩个参数 a "xyz a {b
//c d}"
eval {
set a 22
set b 33
}//eval收到一个参数 "set a 22\nset b 33"

Command summary 命令综述
1.一个命令就是一个字符串(string)。

2.命令是用换行符或分号来分隔的。

3.一个命令由许多的域组成。第一个于是命令名,其它的域作为参数来传递。

4.域通常是有空白(Tab横向制表健 Space空格)来分开的。

5.双引号可以使一个参数包括换行符或分号。三种子替换仍然发生。

6.花括号类似于双引号,只是不进行三总体换。

7.系统只进行一层子替换,机制替换的结果不会再去做子替换。而且子替换可以在任何一个域进行。

8.如果第一个非控字符是`#", 这一行的所有东西都是注释。

Expressions 表达式

对字符串的一种解释是表达式。几个命令将其参数按表达式处理,如:expr、for 和 if,并调用Tcl表达式处理器(Tcl_ExprLong, Tcl_ExprBoolean等)来处理它们。其中的运算符与C语言的很相似。

! 逻辑非

* / % + -

<< >> 左移 右移 只能用于整数。

< > <= >= == !=逻辑比较

& ^ | 位运算 和 异或 或

&& || 逻辑"和" "或"

x ? y : z If-then-else 与C的一样

Tcl 中的逻辑真为1,逻辑假为0。

一些例子:

5 / 4.0
5 / ( [string length "abcd"] + 0.0 )
---------------------- ---
计算字符串的长度 转化为浮点数来计算

"0x03" > "2"
"0y" < "0x12"
都返回 1

set a 1
expr $a+2
expr 1+2
都返回 3

Lists 列表
字符串的另一种解释为列表。一个列表是类似于结果的一个字 符串包含了用空白分开的很多域。例如 "Al Sue Anne John" 是一个有四个元素的例表,在列表中换行父被视为分隔符。

例如:
b c {d e {f g h}} 是一个有三个元素的列表 b 、c 和 {d e
{f g h}}。

Tcl的命令 concat, foreach, lappend, lindex, linsert,list , llength, lrange,lreplace, lsearch, 和 lsort 可以使你对列表操作。

Regular expressions 正则表达式

Tcl 提供了两个用于正则表达式的命令 regexp 和 regsub。
这里的正则表导师实际上是扩展的正则表达式,与 egrep 相一致。

支持 ^ $ . + ? \> \< () | []

Command results 命令结果

每一条命令有俩个结果:一个退出值和一个字符串。退出值标志着命令是否正确执行,字符串给出附加信息。有效的返回制定议在`tcl.h",如下:

TCL_OK
命令正确执行,字符串给出了命令的返回值。

TCL_ERROR

表示有一个错误发生,字符串给出了错误的描述。全局变量 errorInfo 包含了人类可读的错误描述,全局变量errorCode 机器使用的错误信息。

TCL_RETURN

表示 return 命令被调用,当前的命令(通常是一个函数)必须立刻返回,字符串包含了返回值。

TCL_BREAK
表示break已经被调用,最近的巡环必须立刻返回并跳出。字符串应该是空的。

TCL_CONTINUE
表示continue已经被调用,最近的巡环必须立刻返回不跳出。字符串应该是空的。

Tcl编程者一般需要关心退出值。当Tcl解释器发现错误发生后会立刻停止执行。

Procedures 函数

Tcl 允许你通过proc命令来扩充命令(定义新的命令),定义之后可以向其它的内建命令一样使用。
例如:
proc pf {str} {
puts $str
}
pf "hello world"
这里有一个初学者不注意的地方,上述的定义一定要写成那样子。而不能向下面那样写:
proc pf {str}
{
puts $str
}
因为proc实际上也只不过是一条命令,是一换行符或分号来结束的,用集群参数来传递函数体。proc的定义如下:
proc name args tclcommand

Variables: scalars and arrays 变量:标量和向量(即数组)

向量就是数组,而标量是没有下表的变量。
我们用C来类比:
int i; // i 是标量
int j[10]; // j 是向量

变量不需要定义,使用的时候会自动的被创建。Tcl支持两种变量:标量和向量
举个例子来说明吧,
set i 100
set j(0) 10
set k(1,3) 20
i是标量,j是向量。
引用的时候:
$i
$j(0)
$k(1,3)

Tcl 内建命令

Built-in commands 内建的命令

Tcl提供了下面描述的内建函数。
... 表示参数不定

append varName value
append varName value value value ...
将那一大堆value附加到varName后面。如果变量不存在,会新建一个。
例子:
set i "aaa"
append i "bbb" "ccc"
//i = aaabbbccc


array subcommand arrayName
array subcommand arrayName arg ...
这是一组用于向量操作的命令。第二个参数是子命令名。

假设:
set a(1) 1111
set a(2) 2222
set a(three) 3333
一下均以它为例子(tclsh在中运行)。

array names arrayName
返回一个数组元素名字的列表。
tclsh>array names a
1 2 three

array size arrayName
返回数组的元素个数。
tclsh>array size a
3

下面是用于遍历的命令
arrry startsearch arrayName
初始化一次遍历,返回一个遍历标示(searchId)在下面的命令是中使用。

array nextelement arrayName searchId
返回下一个数组中的元素。如果没有返回一个空串。

array anymore arrayName searchId
返回 1 表示还有更多的元素。0 表示没有了。

array donesearch arrayName searchId
结束该次遍历。

array nextelement arrayName searchId
返回下一个元素。

tclsh>array startsearch a
s-1-a
tclsh>array nextelement a s-1-a
1111
tclsh>array nextelement a s-1-a
2222
tclsh>array anymore a s-1-a
1
tclsh?array nextelement a s-1-a
3333
tclsh>array donesearch a s-1-a

注意可以同时并发多个遍历。

break
跳出最近的循环。

case string in patList body ...
case string patList body ...
case string in {patList body ...}
case string {patList body ...}

分支跳转。
例如:
case abc in {a b} {puts 1} default {puts 2} a* {puts 3}
return 3.

case a in {
{a b} {format 1}
default {format 2}
a* {format 3}
}
returns 1.

case xyz {
{a b}
{format 1}
default
{format 2}
a*
{format 3}
}
returns 2.
注意default不可以放在第一位。支持shell文件名风格的匹配符。

1 0
原创粉丝点击