版主
主题
回帖0
积分10609
阅读权限200
注册时间2008-11-22
最后登录1970-1-1
在线时间 小时
|
楼主 |
发表于 2011-2-22 09:46
|
显示全部楼层
Tcl编程简介5 a' H2 Q; J4 T' L2 Q+ e# C, n6 c
简介3 Y" v1 Q2 Z7 m6 H+ r
Tcl是一种很通用的脚本语言,它几乎在所有的平台上都可以解释运行,功能强大,是tool
- G# O. p& M% J9 b( |command language的缩写,发音为“tickle”,实际上包含两个部分:一个语言和一个库。- L" ^2 [# I7 f+ w7 n3 M
首先,Tcl是一种简单的脚本语言,主要使用于发布命令给一些互交程序如文本编辑器、调
& r" g* h- }; W试器和shell。它有一个简单的语法和很强可扩充性,Tcl可以创建新的过程以增强其内建
$ [$ N. V4 h; v- V/ {命令的能力。
% q1 C$ c$ L; ]" O其次,Tcl是一个库包,可以被嵌入应用程序,Tcl的库包含了一个分析器、用于执行内建
8 c" M l% V' O8 y# w2 M. i0 W5 d命令的例程和可以使你扩充(定义新的过程)的库函数。应用程序可以产生Tcl命令并执行,5 Z" a/ k2 f" F3 J! m: n
命令可以由用户产生,也可以从用户接口的一个输入中读取(按钮或菜单等)。但Tcl库收2 V& u2 n& `/ I7 o0 n- q" m
到命令后将它分解并执行内建的命令,经常会产生递归的调用。4 f9 g# h0 i- s8 v
下面简单介绍以下txl的语法规则:
6 i: B' u3 L$ m, {' ?; h" J0 `解释器6 ^2 f, @- w) c$ w9 K: j8 W4 |4 _
在tcl的数据结构中的核心是Tcl_Interp.一个解释器包含了一套命令,一组变量和一些用/ O7 _# O1 P( k4 J. O, ^
于描述状态的东西。每一个Tcl命令是在特定的Tcl_Interp中运行的,基于Tcl的应用程: G; @+ O% q1 W! B1 n0 V/ r
序可同时拥有几个Tcl_Interp。Tcl_Interp是一个轻量级的结构,可以快速的新建和删除。+ P0 H4 i; H' H; H" b9 F' Y
数据类型! W' k2 l; x, S# [
Tcl只支持一种数据结构:字符串(string)。所有的命令,命令的所有的参数,命令的结
* e+ h: d- l& r8 R& L, ?果,所有的变量都是字符串。请牢记这一点,所有的东西都是字符串,是它较有特点的方面。, F1 z3 Y) i& q1 y
字符串有三种形式:命令(command),表达式(expresion)和表(list)。
& z' K$ c# M( s- Y, y3 ~" yBasic Command Syntax 基本语法3 y0 ]* `9 p) C [& j- W+ M' ?
Tcl有类似于shell和lisp的语法,当然也有许多的不同。一条Tcl的命令串包含了一条或* g) R. m. Q0 _0 h6 {
多条命令用换行符或分号来隔开,而每一条命令包含了一个域(field)的集合,域使用空白+ y& _; A9 {) h# M. j% Y
分开的,第一个域是一个命令的名字,其它的是作为参数来传给它。
, [/ \" a# h/ L, P2 ]& e例如:set a 22 //相当于C中的 a=22 a是一个变量: F0 |) h0 h+ ?8 P9 U! Y2 j
这条命令分为三个域:1: set 2: a 3:22 set使用于设置变量的值的命令,a、20作为
) O8 A" A4 y3 g; B/ A4 b参数来传给它,a使它要操作的变量名,22是要付给的a值。
. Q! D$ c5 V% v5 w- iTcl的命令名可以是内置的命令也可以是用户建的新命令,如果是用户用户建的新命令应用. w8 n; s; T+ K' d
程序中用函数Tcl_CreateCommand来创建。所有的参数作为字符串来传递,命令自己会按其0 N: H. U. L* f! [
所需来解释的参数的。命令的名字必须被打全,但Tcl解释器找不到一同名的命令时会用
3 G$ W. s9 z) _; x1 w% Hunknown命令来代替。0 o, @: }0 }! I. a- l6 l" b
在很多场合下,unknown会在库目录中搜寻,找到一个的话,会自动生成一个Tcl命令并调4 L6 q4 e: D0 s8 v2 R% }1 w. H
用它。unknown经常完成缩略的命令名的执行。但最好不要使用。+ K$ y5 M7 P; }# p& U
注释6 _& g9 W$ B9 j9 ~, ~
和shell很象,第一个字母是"#"的Tcl字符串是注释。8 y8 |% \9 Q+ _* s3 G1 K. \( j
其他细节规则
4 P, `, H: x0 a. sGrouping arguments with double-quotes 用双引号来集群参数,目的使用有空白的参数。
. c# C o7 o, W例如:
4 |5 e" T# V4 ^5 Wset a "this string contains whitespace"( Y _4 T* a, r' e' o/ n
如够一个参数一双引号来开始,该参数会一直到下一个双引号才结束。其中可以有换行符和: _, G7 P5 t% W& E& b) l. S
分号。1 r1 X- f: R- s; @" o
Variable substitution with $ 用美元符进行变量替换说白了就是引用该变量。
! f! F) P3 J' J3 G' Y/ g例如:
~: S) ?) j+ S, s$ ]5 L' Uset a hello
) v/ M5 ~# j2 u+ sset b $a // b = "hello"实际上传给set命令的参数//是b,"hello"
8 v1 t8 m8 V- Dset c a // b = "a"
8 }! m2 a/ r3 ]+ a7 LCommand substitution with brackets 命令子替换(用方括号)+ x, w9 [! O& z0 D7 I* e+ C
例如:
4 X L% [6 L3 k. Iset a [set b "hello"]
" @" i+ `0 I2 h( B+ D( f+ ~; n8 Q实现执行 set b "hello" 并用其结果来替换源命令中的方括号部分,产生一条新命令0 P/ g) w& v' s. |/ M" p0 @5 f
set a "hello" //"hello" 为set b "hello"的返/回值最终的结果是b="hello" a="hello"7 U3 d- j9 `* i/ q; \
当命令的一个子域以方括号开始以方括号结束,表示要进行一个命令子替换。并执行该子命
* o! ~9 ]( M8 P/ T8 ?2 A9 p1 f令,用其结果来替换原命令中的方括号部分。方括号中的部分都被视为Tcl命令。) I* r# k' f8 p8 o, K4 z9 d
如下一个复杂一点的例子:
# G+ }0 Y0 }6 E; E, @set a xyz[set b "abc"].[set c "def"]
& W7 e# k. \& u$ z//return xyzabcdef
w" m2 G3 P! Q4 iBackslash substitution 转移符替换
0 i* X% `5 i' m" u3 r转移符时间不可打印字符或由它数意义的字符插入进来。这一概念与C语言中的一样。
% V6 ? D# J7 i9 j7 EBackspace (0x8).
I/ M6 x/ E+ m/ p `$ Rf Form feed (0xc).% _, ]; G$ a8 D% `+ B, S! `( Y
Newline (0xa).& O% K! t4 {8 r5 c; g* V
Carriage-return (0xd).
6 D' a+ i! |/ @! s1 zTab (0x9).% p) _' }7 V9 E. C( n( Y5 b
v Vertical tab (0xb).0 n7 v0 |% e' A) _
{ Left brace (`{").7 U# @% v* s. j) a! z
} Right brace (`}").) c9 r7 S# R$ @- W; Y- z6 G
[ Open bracket (`[").4 A2 u( |. ]9 L) i8 V1 C! C
] Close bracket (`]").
$ t, M, W0 O8 m$ Dollar sign (`$").) g& V0 c$ m, q: r% C( |) u7 U {- ]% E
sp Space (` "): does not terminate argument.) w, c G8 d: P3 c' @8 a9 z
; Semicolon: does not terminate command. r3 K o) U1 x, \9 A. b! o
" Double-quote.0 I/ ?; L2 @# p
Grouping arguments with braces 用花扩括号来集群参数,用花扩括号来集群参数与用双+ ~7 q5 b! K% q3 j
引号来集群参数的区别在于:用花扩括号来集群参数其中的三种上述的子替换不被执行。而
# @/ n/ ^6 E/ `! |% t' z且可以嵌套。: K6 R$ i; ~) f6 \8 z
例如:
- X6 S% i2 w Y2 u+ m8 Xset a {xyz a {b c d}} //set收到俩个参数 a "xyz a {b//c d}"
' S1 J/ }5 l3 Peval {
2 ~/ ^9 m& U; q) y4 Mset a 225 R8 z& A9 h$ ]( D' M3 m
set b 33
, h7 r3 X. C! N: _2 L* V. W2 g}//eval收到一个参数 "set a 22+ P# C' V8 O+ |7 [" M
set b 33"& c! e$ N3 y, [$ i
命令综述
+ Y" h7 o& j# T, n r1.一个命令就是一个字符串(string)。$ z/ p: F9 V# H/ u6 _
2.命令是用换行符或分号来分隔的。: t% o- }" A1 b! S2 H9 s
3.一个命令由许多的域组成。第一个于是命令名,其它的域作为参数来传递。
& c$ `: @/ {2 t; ?4.域通常是有空白(Tab横向制表健 Space空格)来分开的。9 q. k7 s/ P0 i p3 z
5.双引号可以使一个参数包括换行符或分号。三种子替换仍然发生。
4 P' J: f7 F5 ~2 A a# h( \4 r( g6.花括号类似于双引号,只是不进行三总体换。
6 Z9 d* W- V) w! ]7.系统只进行一层子替换,机制替换的结果不会再去做子替换。而且子替换可以在任何一个0 @9 ~2 ]5 I! v ~5 H3 O
域进行。
/ o; t" B' u: B. P; p# Q8.如果第一个非控字符是`#", 这一行的所有东西都是注释。
* k7 c* ?: Z! Z% m2 d) ]表达式" |" U! l6 Q# {' [
对字符串的一种解释是表达式。几个命令将其参数按表达式处理,如:expr、for 和 if,并: ^" u8 I. z9 i+ A$ I( |& }- `
调用Tcl表达式处理器(Tcl_ExprLong,Tcl_ExprBoolean等)来处理它们。其中的运算符与C' O6 a: S0 r, b. F- ^1 P0 Z
语言的很相似。
( k% k* o- i0 n) E, ]4 R, j+ X2 g! 逻辑非
2 }! q9 W, d0 v* w: S" u* / % + - 加减乘除余数- U6 R5 n) g4 ?8 n& u
<< >> 左移 右移 只能用于整数。
6 b& o+ l) x0 U! @% A! v6 P< > <= >= == != 逻辑比较
! y5 H+ W8 V% m' P; `& ^ | 位运算 和 异或 或
, E6 U- o9 ?; P0 D: J&& || 逻辑"和" "或"( G" R' T$ U- n, J
x ? y : z If-then-else 与c的一样
/ ^7 c7 X- T! I& y- Z* o# C: W! q3 w. ZTcl 中的逻辑真为1,逻辑假为0。. i- i) ~/ K7 T0 e
一些例子:6 ?7 z( ~) U1 f- n( J0 l- {
5 / 4.08 l! D& Q( \* l- b5 ~+ P: P7 P
5 / ( [string length "abcd"] + 0.0 )
, ~6 B8 T% X. l1 \$ @7 G$ N0 r---------------------- ---* J( t, i; b7 B* q6 \
计算字符串的长度 转化为浮点数来计算5 ^% p5 J/ x- g; W( ^' t% \ m
"0x03" > "2"
3 P( h* k! ~5 n* G& S) Z% \: }; J"0y" < "0x12"
. O: z) q; O, ]' V3 S3 a1 F都返回 1
- I& {- Q/ e. w0 u8 K8 M1 bset a 11 X ]' H3 L$ K1 f! W5 |: S, \
expr $a+29 [1 A8 {9 E% x& `
expr 1+2, d) _. O% W o' r; l0 z7 F! o& E
都返回 36 F" u! i2 E: i1 D7 J- b
列表+ m& s, c+ S2 K$ i. `; x
字符串的另一种解释为列表。一个列表是类似于结果的一个字符串包含了用空白分开的很多0 t* C) n9 ?! T, n$ B6 u; F2 k
域。例如 "Al Sue Anne John" 是一个有四个元素的例表,在列表中换行父被视为分隔符。. A$ L0 ^/ T0 a
例如:& H# B$ Q+ h- P5 G: `6 m6 b; h
b c {d e {f g h}} 是一个有三个元素的列表 b 、c 和 {d e {f g h}}。
5 L' ^% U* l" w4 f. v: sTcl的命令 concat, foreach, lappend, lindex, linsert,list, llength,lrange,lrepla
+ K1 ?2 I# \0 p- ]5 E" Oce, lsearch, 和 lsort 可以使你对列表操作。
/ {( K7 O6 X3 `0 k! r# y正则表达式
7 K; O/ M# w: @5 rTcl提供了两个用于正则表达式的命令 regexp 和 regsub。这里的正则表达式实际上是扩
6 ?* @. Z! v) p( e展的正则表达式,与 egrep 相一致。
' }' z. ^) D* f" Q6 W: o0 x* \支持 ^ $ . + ? > < () | []
, P6 ^' n/ T# Q. p3 f命令结果
, j i8 Z }% ~; [) h$ F+ }% [每一条命令有俩个结果:一个退出值和一个字符串。退出值标志着命令是否正确执行,字符
$ Q# \( c" v/ P! l& X) r; Q5 q7 h& t串给出附加信息。有效的返回制定议在`tcl.h", 如下:3 e8 Z( M& [7 ~4 ?; F
TCL_OK! G. {: |5 m& @/ Z4 N
命令正确执行,字符串给出了命令的返回值。
6 x7 O1 U, Y% W$ @% O. O, J9 uTCL_ERROR
2 t! B2 G2 r0 \3 a( x, B表示有一个错误发生,字符串给出了错误的描述。全局变量 errorInfo 包含了人类可读的
/ b N3 y2 p5 D8 g) I3 t错误描述,全局变量errorCode 机器使用的错误信息。: s0 C% C* p$ L* L
TCL_RETURN q4 M$ }& D. ^( D3 F T3 B
表示return命令被调用,当前命令(通常是一个函数)须立刻返回,字符串包含了返回值。
$ z4 n# Z* {- \TCL_BREAK7 s: E8 v1 d' _" ~1 [
表示break已经被调用,最近的循环必须立刻返回并跳出。字符串应该是空的。
& ?" I4 G( u: }( e% ATCL_CONTINUE) W' \8 Y, X% f4 k# ~+ P' U3 H) `) M
表示continue已经被调用,最近的循环必须立刻返回不跳出。字符串应该是空的。2 M# a e7 n! N( m4 h' I% v
Tcl编程者一般需要关心退出值。当Tcl解释器发现错误发生后会立刻停止执行。$ g" N) C0 X8 t, _7 b$ b/ g
Procedures 函数
# p2 x0 i' N9 D8 N X, \. UTcl允许通过proc命令来扩充命令(定义新命令),定义后可以向其它的内建命令一样使用。! ?, O; Y: i' {
例如:# G x; |( I$ g3 t6 ^* i3 W
proc pf {str} {
9 y5 T2 z2 C' }" N% [puts $str
9 e. J T% ]3 g+ i' J+ \}
0 J {! r! ^4 [8 }" ~pf "hello world"1 u; x6 B0 y7 `
这里有一个初学者不注意的地方,上述的定义一定要写成那样子。而不能向下面那样写:
2 S1 I* f# F, e9 c8 cproc pf {str}
' b+ p0 F2 u* n+ D" f{3 P0 K& {* y6 U3 B- |7 r
puts $str
5 w7 ?6 I. H6 ^/ S# V+ ]8 E! y}
, k7 l3 c6 ^, x, ?因为proc实际上也只不过是一条命令,是一换行符或分号来结束的,用集群参数来传递函" b# k3 K7 R2 r( \7 y
数体。proc的定义如下:
) F" V+ {* f3 wproc name args tclcommand8 J+ m7 ~ D- \. @3 r: ]2 Q( Q3 c3 r
Variables: scalars and arrays 变量:标量和向量(即数组)
5 F" g# n- O- [- g向量就是数组,而标量是没有下标的变量。9 A6 ^2 ?9 t$ J* J m% h7 H- e
我们用C来类比:
' i1 {2 S% X( j& b' Vint i; // i 是标量. L9 l- K/ g! u; Z/ Q! U+ m: W$ m, j# i
int j[10]; // j 是向量
" I/ y( [! n& L/ D. g变量不需要定义,使用的时候会自动的被创建。Tcl支持两种变量:标量和向量,举个例子
& J L3 E- i# o4 W来说明吧:
) b ~' S. ~6 B6 ^) J# {( _8 y" j2 bset i 100
8 G# l3 E* N: Y% @set j(0) 10
/ J# H; w: J1 {6 U% n7 o% Aset k(1,3) 20; P( a9 {5 Y3 g' ^9 g
i是标量,j是向量。# i7 m: a* p& e
引用的时候:
( q% ]; F6 }" Q1 }$i
, ]/ V0 R1 b* N+ _$j(0)( ?9 b5 D# {6 g5 D G0 {
$k(1,3)
; e' W/ @" L# p, `5 G( PTcl 内置命令
1 i6 I0 ~* V4 A8 y2 U+ t内置的命令4 ]- A% O5 u6 B* F' }; I
Tcl提供了下面描述的内置函数。其中: ... 表示参数不定,具体有:* F# W) Y( Q+ e& |+ d3 r1 G% j) D7 ^3 T" C
append命令:+ w& u1 Q7 v6 d/ i% q
append varName value
0 t& d, l# | G7 d; X; nappend varName value value value ...
7 S, |+ I$ @ D; _将那一大堆value附加到varName后面。如果变量不存在,会新建一个。
$ x6 r: o3 I* p! _, M# y例子:, F3 e) {5 f) ~( f2 G, N! z% I
set i "aaa"6 _% K0 [5 S7 b- g
append i "bbb" "ccc"
# s: F1 C' u4 Y F//i = aaabbbccc
5 M s; ?4 B- M' W |$ Narray命令:! {, V8 v2 \! L/ H, [5 y1 S* ]& w
array subcommand arrayName6 G* W k% A" G" s# b/ Q
array subcommand arrayName arg ...
. z* f/ o. n9 \. c% w/ }$ Q# I& K" E这是一组用于向量操作的命令。第二个参数是子命令名。8 X, j. L4 k9 V3 J
假设:4 L# D5 k ^, k& J+ m( X
set a(1) 1111
# N2 \* e2 c) ]6 W" h; c5 j. dset a(2) 2222
3 h$ I5 E2 A* \' y, I5 Zset a(three) 3333
( U6 e) l+ V2 h# L以下均以它为例子(tclsh在中运行)。
8 ?7 g* t ^ |+ K& harray names arrayName
. q8 g) C7 L: u4 w! R返回一个数组元素名字的列表。# B7 x; `6 y0 V7 G$ M: G
tclsh>array names a" M4 o* T) o; U' W7 h+ g
1 2 three
3 H/ s$ K- O' U- b. T, P' l' |array size arrayName
8 R9 P$ \6 [* d& P o返回数组的元素个数。, Z, I6 J/ F) w7 E
tclsh>array size a# B m+ G Y; Z; ~. e" N
34 z$ @1 u* J8 {/ g
下面是用于遍历的命令
$ [ O# K; m. A- }, y. @( darrry startsearch arrayName" A& g7 P( H( m' _
初始化一次遍历,返回一个遍历标示(searchId)在下面的命令是中使用。
/ K) N% D' e2 J- [/ Karray nextelement arrayName searchId
/ I0 R% ]0 z5 w3 R0 \- d返回下一个数组中的元素。如果没有返回一个空串。
" I& l+ i$ O; |7 @array anymore arrayName searchId
l& P: S# n0 ?# E' d5 P返回 1 表示还有更多的元素。0 表示没有了。
/ Q% L1 v9 f. U- E' q( Parray donesearch arrayName searchId
/ k% V2 ]2 I2 m9 w i结束该次遍历。, q: {4 k( j4 r) o' N0 y6 H
array nextelement arrayName searchId
! i7 g6 p. A% p返回下一个元素。
# Z, B9 y( m- D* M9 Btclsh>array startsearch a, o: c; s: b+ L; h& d
s-1-a
2 U1 t8 S+ w% S b3 k# dtclsh>array nextelement a s-1-a) z; ]! W, t$ g
1111
1 m! @2 K: p# i+ P5 |: ktclsh>array nextelement a s-1-a
p* b# l) h3 u6 w5 W, d' ~2222; J4 }' d/ H; [
tclsh>array anymore a s-1-a
2 P+ J0 z! O( G, c$ i6 h1
3 r+ K% w, U6 itclsh?array nextelement a s-1-a; A" |+ z% V j, t( a
33339 B y t' r* N. r
tclsh>array donesearch a s-1-a
2 N5 C" f' b+ v2 m" ~9 u" \注意可以同时并发多个遍历。
4 `( X4 {1 w" w* ^6 J( a1 |break命令
$ e: v1 n- Z8 F1 Ybreak
% T: Q, l4 h( L" x跳出最近的循环。
% r" K v- g# |& l7 O6 Tcase string in patList body ...' N5 K; h0 _: d5 G* O
case string patList body ...
; R) E5 G6 O0 u% p/ q9 j" Jcase string in {patList body ...}
2 X6 t" e; }6 c! Ucase string {patList body ...}
- R8 `+ H& V# A, L& b$ t分支跳转。& F& ^2 ]* ]3 r* ?9 g# K
例如:
3 `3 ^2 e8 Q7 x/ Pcase abc in {a b} {puts 1} default {puts 2} a* {puts 3}: I3 P2 p2 Q% Q- [% m
return 3.# g+ ~* h6 P/ b# w
case a in {
2 c+ r# w0 b- b{a b} {format 1}
" T! x2 |0 E/ S' Ndefault {format 2}& s2 q8 [7 y/ d* Z' [
a* {format 3}
7 |9 {( ~- y6 H- R}
7 U/ \& [: _( q9 b5 ?returns 1.
* a/ i- b& L1 e: [. Rcase xyz {. {, ]8 C: q4 S: J3 J5 t, R
{a b}
1 {. M9 a" d: T0 u2 H' k{format 1}
9 h: J3 H2 Z% G1 Z3 u& P9 U3 fdefault
. l N( G, e) b6 Q& j [, n% A J{format 2}
; _# r" ?4 Z7 q, r( m, ka*) L, ]& L( o6 i' D
{format 3}- Q; I1 x. ?$ u, v5 {
}
% C* [9 [. h, H* [& D6 greturns 2.
, X- {* C6 s5 ^# g注意default不可以放在第一位。支持shell文件名风格的匹配符。% B* t A, x1 r; @) ~' G: z$ u6 w
catch 命令) h9 Z G- o' }
catch command varName! ?- t3 N2 v. D- {
用于阻止由于错误而导致中断执行。执行command,每次都返回TCL_OK,无论是否有错误发1 |+ l' ~- I0 P y9 b6 L: z
生。如有错误发生返回1,反之返回0。如果给了varName这被置为错误信息。注意varName4 v1 n1 ] _. ]/ f& J; Z9 }3 q! n
是已经存在的变量。' I6 ]$ g( I( m1 u3 l8 e
cd 命令(如shell)
, i' @7 l G1 S e0 @4 s! c1 Ycd dirName# y- F2 `" k$ T. ]& ?# b( `
转换当前工作目录。如dirName未给出则转入home目录。3 N& C( _2 k5 _* A/ c4 U
close fileId
$ A/ S( p. a4 \! H关闭文件描述符。
7 O$ q' l! [! f6 Q( B7 Zconcat arg ...
, y: t3 C3 e; x将参数连接产生一个表。
! ?% Y$ N" |, i' D* R6 y4 @% Q; [concat a b {c d e} {f {g h}}8 y- ~/ m& {7 Q x# n
return `a b c d e f {g h}"1 R% [& \# p p, [# T6 j
continue+ p1 r& o# m# E8 l* u
结束该次循环并继续循环。
]* R8 O: b4 Y, Beof fileId
5 S' [# L$ f' b; {2 v: E9 c如fileId以结束 返回1,反之返回 0。
2 c; v1 J7 q; i$ `! q# q$ H) s0 \; SError命令3 X6 K' k: D% H; t1 Z/ W
error message3 Y2 i7 w$ [2 _6 _* K5 D o, x/ R
error message info! b! i; _' {- E, Z9 N* Q/ O! n/ }
error message info code
/ U0 }. o6 G, g7 s返回一个错误,引起解释器停止运行。info用于初始化全局变量errorInfo。code被付给
1 i0 A% W* d: w! d0 P! ?) `errorCode。
+ i: M4 T' ]. peval arg ...2 c8 u0 h& q. l8 Z$ L) H) C
将所有的参数连起来作为命令语句来执行。
, f. V( m+ Q' D( lexec arg ...6 Z+ y6 ~9 L) p
仿佛是在shell下执行一条命令。
2 a( w( `) |. Q6 Fexec ls --color
& ~/ R6 s# Y# pexec cat /etc/passwd > /tmp/a3 u4 @; c. t& u* S6 f0 f4 @0 _
exit
9 q3 m# x! \# H+ Z; L7 h6 n0 Eexit returnCode
- p+ r, ~* l. B9 u' M中断执行。
0 B u3 O3 T/ H( @6 [( W! L/ J$ Hexpr arg
5 F; t% R P+ N$ x- K' i$ i处理表达式。6 {+ F6 B3 O9 [) `8 y
set a [expr 1+1]
- l( y2 @# W; d& K: W; {4 v/ D0 C: Q//a=2
8 h9 C5 l2 v) T( | D& J5 o% [file subcommand name3 O8 r$ T P0 M
一组用于文件处理的命令。) `3 j3 y" u$ M0 q: q* w4 Z! {
file subcommand name arg ...5 g. P' x6 n4 H8 W0 {- v
file atime name
0 p' Q0 g4 R8 B/ g# U4 s6 b0 f返回文件的最近存取时间。2 F" S8 b7 u8 ]% o2 i" J4 @% Q
file dirname name
' O% [' A( ~ ]返回name所描述的文件名的目录部分。
0 X2 P# k2 P# o- ~7 R9 S) _+ Ofile executable name
3 T& E4 N8 r1 N1 J1 |# Z6 x: H返回文件是否可被执行。% R4 g+ S- R# [5 c/ D
file exists name0 w7 s5 \; E% @4 m
返回1 表示文件存在,0 表示文件不存在。
$ p# K2 j$ q2 ]: b9 Gfile extension name) }2 }* v( W5 A$ [
返回文件的扩展名。
% d0 E1 J5 X# {7 ^0 F/ C0 @file isdirectory name
! Z' R' z; M- A* ]# [判断是否为目录。
2 l Q6 R* ]+ H2 {file isfile name
' F: ^+ X/ S n% }# C判断是否为文件。9 E0 \6 O& h' k* \6 \9 o
file lstat name varName
5 [; y- I3 E8 c5 f% M以数组形式返回。执行lstat系统函数。存储在varName。6 s ~# k, T* r) {8 d) h
file mtime name
$ a# E& n3 T8 ]+ O/ }+ K文件的最近修改时间。7 _, f& E5 q2 z3 x8 @" K& \8 ^) q
file owned name
# m9 g' v1 s7 d# O+ K+ v判断文件是否属于你。! o4 f/ B$ T0 W. l8 a. R
file readable name
+ W6 U# x# c7 {4 I7 a0 _判断文件是否可读。0 F5 T- V l9 L, u! l
file readlink name& [3 K f8 L3 X( `5 A6 h+ {) o
都出符号连接的真正的文件名。
% H2 G' u# a( h& V, Y4 B; n! {6 Nfile rootname name8 i0 T% c6 P, Q9 @: P/ d
返回不包括最后一个点的字符串。
, Q( x8 ]1 k6 p% R3 |* bfile size name; J6 l8 P4 t+ E/ X9 }
返回文件的大小。
$ o) m p2 v1 |1 ^8 e U$ Nfile stat name varName
5 L. k+ {+ L! f2 r. t& M. Q调用stat内和调用,以数组形式存在varName中。
" S. p: }5 O |3 ^: Kfile tail name b: }0 }5 e; V2 L5 i M8 N: w
返回最后一个斜线以后的部分。) {/ u9 ]5 t6 S n* c8 O/ z. Q
file type name3 E: L2 a5 x9 h8 _/ e4 g4 `
返回文件类型file, directory, characterSpecial,
4 z" A7 W* k/ W7 L g8 H2 KblockSpecial, fifo, link, 或
% U& Z0 U8 ~" W0 R- zsocket。; k6 O5 Y( O: l# y0 P9 j. t
file writable name. t7 y- K8 Y3 E
判断文件是否可写。
3 ^+ W0 {6 N8 A& T% ]; i: C0 j0 hflush fileId/ B) A; n2 W5 q' w
立即处理由fileId描述的文件缓冲区。
* ]+ D$ z9 G* qfor start test next body9 r2 {3 Q9 ]' s" Z
for循环。同C总的一样。* b* `. y3 Q0 o3 X$ z% r7 C. V
for {set i 1} {$i < 10} {incr i} {puts $i}
7 { e1 v# v: P, Hforeach varname list body. ]/ e/ I3 g6 u3 V8 a
类似于C Shell总的foreach或bash中的for..in...( C7 ~% Y8 F; I6 e( U
format formatString- P# y+ P& M h8 }# g0 @5 L* y. q
format formatString arg ...
0 n9 h1 x" c! ` D: v格式化输出,类似于C中的sprintf。2 P4 g0 D, u& ^ h, \0 N
set a [format "%s %d" hello 100]
- _3 q0 X. ^6 B0 \//a="hello 100"* Y7 k* E/ Z* K& p0 |" U: x( B' s
gets fileId
! @* n( o$ B& Lgets fileId varName
0 c+ E+ C9 U7 b+ a从文件中读出一行。$ Z. g& B, I8 c3 z: e% M* ^
set f [open /etc/passwd r] P l2 `+ N) L! I4 L
gets $f, B6 z5 ~, Q& f) ?/ D
glob filename ...6 ~0 t' t% o, Z; O) K$ n
glob -nocomplain filename ...8 h+ W/ o# E2 @% ^; M9 X# I
使用C Shell风格的文件名通配规则,对filename进行扩展。
: j7 [3 Q( }8 @2 jls /tmp
- Q, b# P2 ?" L6 G9 Ha b c
8 N* R1 O% X0 s1 p& ]/ R( o" W" Ttclsh>glob /tmp/*
: W6 ~# u* k) h2 Ca b c
" t7 O7 ~0 e0 }. a* V当加上参数 -nocomplain 时,如文件列表为空则发生一个错误。7 u0 p* e* h6 `
global varname ...
) J4 R6 G+ D7 @9 p k- T& C: r# |定义全局变量。
$ p9 v" U1 B3 M: R; ~" I3 U2 ?if test trueBody1 o$ ~" o) d5 _1 B) V8 O
if test trueBody falseBody4 v6 n, J% d) }# v- H4 M
if test then trueBody
0 f4 h/ c, I. l3 g( {$ ]2 f- O9 m7 \# xif test then trueBody else falseBody- y+ m) T8 n W+ p
条件判断,实在没什么说的。
6 c1 d+ J$ D" _, u1 p: ^incr varName2 W2 k5 Z8 c8 A) I( K+ p2 B
incr varName increment
% \! i/ w' h2 }: C# f) b如果没有incremnet,将varName加一,反之将varName加上increment。/ r1 N' B( ~$ {' Y+ O+ V
set i 10
2 r0 K$ M( D) O% R& [/ W7 ^! }incr i
8 L6 u& A- D" P; @) h+ E//i=117 ]. N, ^5 J" c0 `- V
incr i 10# n& ~ m& ^7 d6 x
//i=21' O& x5 J* @, f2 F2 `! h
info subcommand
2 n" @- U$ z; ? l9 winfo subcommand arg ...
q f" @; Y( U& N3 H& b取得当前的Tcl解释器的状态信息。2 |5 }$ ^- a( R& ]3 X+ Y) v
info args procname s/ @ w2 d' T
返回由procname指定的命令(你自己创建的)的参数列表。如:
% t/ V% }9 s( E% ]& D7 rproc ff { a b c } {puts haha}) ~8 i& j) ?) J. B0 Z a+ h
info args ff
/ }; J$ |& R. |& {8 T7 d//return "a b c" 7 U, b6 Y9 I5 g$ o' q- p
info body procname5 h% e0 z5 H0 Q4 z$ c1 S+ s6 {
返回由procname指定的命令(你自己创建的)的函数体。如:5 n' k; X4 ~2 ^0 v, O& P
proc ff { a b c } {puts haha}
2 K, v& T8 ?+ L% @! ^ L5 minfo body ff
) J- c: P' T$ U$ N' @//return "puts haha" 6 h( Z3 A* f$ n/ i% s0 ^3 n* {
info cmdcount# ^& f$ U' U5 W: x$ h2 A5 Z$ |
返回当前的解释器已经执行的命令的个数。
7 Z& q" q& E0 E0 `# {: r/ Sinfo commands& r( W" k ?# _; D# h) e
info commands pattern- h7 O0 N# U3 ~7 b
如不给出模式,返回所有的命令的列表,内建和自建的。模式是用C Shell匹配风格写成的。8 y. w7 U8 r+ H! \" o. A
info complete command
1 \* w! e g$ Y5 P6 u' ]3 L* ?4 b检查名是否完全,有无错误。7 w8 V9 r5 ~5 r
info default procname arg varname
: M$ U2 V; n; p$ l1 ]( gprocname的参数arg,是否有缺省值。0 R( C* K7 {- o3 S" m" J
info exists varName
{% {! }& g4 }0 A# F5 a( @1 q; A( i判断是否存在该变量。
, j( S0 _4 a- [9 Uinfo globals2 L6 ? m" w5 G
info globals pattern+ R; `; D) }4 ^* J- D3 I* S9 t
返回全局变量的列表,模式同样是用C Shell风格写成的。
. @: G6 J% R" i! \( Dinfo hostname% q2 P/ P& @; S- D
返回主机名。; O8 d; {4 }7 u' o4 k: U
info level
6 J6 U2 x0 x; k" [info level number
- ?: [ e' w. y: {0 y如果不给参数number则返回当前的在栈中的绝对位置,参见uplevel中的描述。如加了参 R' D' g' p2 K- t
数number,则返回一个列表包含了在该level上的命令名和参数。
5 S% s$ g; H1 w3 U; ]7 Q' C- winfo library* J- i' C. o6 G
返回标准的Tcl脚本的可的路径。实际上是存在变量
4 g' U. c/ c: l- ctcl_library中。3 X0 B/ u. d4 x, `# Q" o- L# P
info locals5 {, G/ k) I! ^! [. k: s
info locals pattern/ X( u9 O [3 y& ?8 U6 J
返回locale列表。! F0 y7 R0 B/ R: V2 }- d
info procs
* K' m, `- I3 d. @4 ~- Winfo procs pattern. y$ a7 Q2 Z! ^. s
返回所有的过程的列表。$ f& i' K) R2 L) g# \ `
info script
0 n b2 y* w* Q. p) w返回最里面的脚本(用 source 来执行)的文件名。+ D* S1 o( \1 G
info tclversion" N# h) f% m& c8 r1 ~
返回Tcl的版本号。
6 P- U. j, c" x" r- ?4 Qinfo vars( E) U/ |; K; ]' Z
info vars pattern
$ L d( B4 E7 w* u7 S0 R9 e# l返回当前可见的变量名的列表。& @: K( C9 t" X( H% E: r* C! \6 t
下面是一些用于列表的命令,范围可以是end。
3 S# L3 J' m" ojoin list
( j4 @) J; D* N" ^6 V2 S8 E. U4 f" ^join list joinString; B9 h1 I& V- w- i* Y: l
将列表的内容连成一个字符串。
7 C1 X5 F6 \/ ], r4 f9 t8 hlappend varName value ...
! v) I, G; O5 A% q4 g将value加入列表varName中。
3 T; F9 R3 r klindex list index) }0 _" m, e9 A- ]# Z8 u0 \0 g5 J
将list视为一个列表,返回其中第index个。列表中的第一个元素下标是0。* r3 g3 i: t( Y: @7 _" c
lindex "000 111 222" 1
4 Q% v- r! r% n* G1111 x% G5 m8 W1 E+ b$ }& H
linsert list index element ...& l# Q% ]. w u" R
在列表中的index前插入element。3 F: s4 U8 Z; w
list arg ...
7 \' X: ?. G$ x9 P/ p将所有的参数发在一起产生一个列表。
0 X. M5 |3 L% {# B4 ?( ]( Vlist friday [exec ls] [exec cat /etc/passwd]
/ q9 F" k# l0 C$ z3 e- S7 tllength list
) I: ?2 B2 w$ }3 {" s1 T( V返回列表中元素的个数。
1 H0 B2 S$ x$ c0 P D+ Nset l [list sdfj sdfjhsdf sdkfj]
! @- N- _, F& Fllength $l
0 l3 o6 q% m! m1 @//return 3) ^* v0 ~ i6 K3 f, M" a
lrange list first last
" c- J/ t* a+ C. ?7 ?返回列表中从frist到last之间的所有元素。0 X7 S. g7 m4 k
set l [list 000 111 222 333 444 555]
, v; h! y+ y; ~9 U+ b% Z9 W+ Olrange $l 3 end
, {8 y$ c1 B6 J( k0 X& d, [//return 333 444 555
+ C7 l) _3 [* Q" llreplace list first last
2 M) F8 D& ]. L3 T& i) S! _3 ^lreplace list first last element ...
* z8 Y$ h3 a3 L/ Z" _3 {替换列表中的从first到last的元素,用element。
5 z& u2 w) R& I( uset l [list 000 111 222 333 444 555]1 a* N; A! l6 ?$ @& b2 F( }/ r- K
lreplace $l 1 2 dklfj sdfsdf dsfjh jdsf1 }& `5 }2 }# v1 `( y
000 dklfj sdfsdf dsfjh jdsf 333 444 555
, x' f# {7 s! E$ l r+ U, F& Ulsearch -mode list pattern# B& I% F7 F& l9 A6 M6 `
在列表中搜索pattern,成功返回序号,找不到返回-1。* F# y+ t8 y2 H& B" ~# n; f9 t' L
-mode : -exact 精确
7 e. w, Y* A8 s% Z-glob shell的通配符! ?9 f# ~! B9 G' A# r' c L4 m
-regexp 正则表达式: O" H8 b7 u! m, b: ]
lsearch "111 222 333 444" 111% G. y! d5 z+ M; X1 j, J/ K/ }
//return 0
) Q4 P6 K% n/ r# V' ylsearch "111 222 333 444" uwe
$ d3 n3 }) x7 J//return 1
; W0 Q! M) Y9 ^- p2 O/ dlsort -mode list
1 h* S( M& z6 G# d. B- i; a排列列表。4 x9 ~! Y3 d8 @% Q+ A9 c
-mode: -ascii
: ?* J* l- P) G5 _9 y9 D6 ` }-dictionary 与acsii类似,只是不区分大小写+ A* E4 [9 Y9 U$ j2 l Q. j4 \
-integer 转化为整数再比较
0 A/ w' A, P6 ~, S9 V-real 转化为浮点数再比较- b5 l- Q, G* N: S+ x
-command command 执行command来做比较
" S I/ ?& V5 U4 ^& P8 J7 S3 C2 ^# mopen fileName: \ i& h% K i# f6 Z' @
open fileName access
1 J( Y7 n+ U) b/ r% |打开文件,返回一个文件描述符。
5 }7 d8 a5 Y: p. Y& W* }/ uaccess
* {$ O8 h9 K; Y! S' }. y/ F8 hr w a r+ w+ a+2 m8 i6 r5 b& d9 D5 p
定义与C中相同。如文件名的第一个字符为|表示一管道的形式来打开。
9 Z8 M9 c8 q6 S# e1 J6 q; fset f [open |more w]
3 _& d) J( V: h8 ^" O* Rset f [open /etc/pass r]
4 y, g1 q0 C' a5 E" lproc name args body" c! X$ d, Y& s: Z/ m0 A/ r
创建一个新的过程,可以替代任何存在的过程或命令。; R( U. k$ E$ B) o
proc wf {file str} {
! o% x* X9 y/ _- z0 E- I$ Dputs -nonewline $file str
" g% F* a; {6 v( w2 A7 t% j pflush $file
8 u. E6 k q1 f6 ^& T}
# }9 d# o' E( g' F( ~" N3 d1 O4 aset f [open /tmp/a w]$ ]/ Q% C6 M4 A+ A" B
wf $f "first line "; a4 y4 z" S6 q& l# A" d {
wf $f "second line "
1 E; e. z* S) O# O" L W) m: h在函数末尾可用 return 来返回值。
5 E0 r7 A9 ^) L" nputs -nonewline fileId string
$ J" ~' ]/ ^- p$ o向fileId中写入string,如果不加上 -nonewline 则自动产生一个换行符。! D6 C' o0 {. [( c7 i
pwd
3 F6 d( Z3 Y$ A( b返回当前目录。" w5 ]8 h" O) I* P9 g0 I
read fileId
5 |! }7 V @2 L2 H5 yread fileId numBytes& d$ P1 m; f- s
从fileId中读取numBytes个字节。
* k- @+ ^3 H( g& mregexp ?switches? exp string ?matchVar? ?subMatchVar
x- J1 } F. O# o" l" OsubMatchVar ...?
1 ^* ]. N5 `( O执行正则表达式的匹配。3 L5 t& L% u& _# z+ Q8 R* H# t5 c/ R+ g
?switches? -nocase 不区分大小写* ?9 T% ` F! m4 M5 Z: m
-indices 返回匹配区间# A. N& B5 q. ~, c9 Z$ O
如:; e8 R8 \) `' \4 \
regexp ^abc abcjsdfh0 I* G4 h5 |, r: y( c- H3 t
//return 14 s0 C* F4 U. `: t+ A" E& d
regexp ^abc abcjsdfh a
: g5 o. v9 r9 T. C//return 1- h( K' H ?; Z) i. U
puts $a' B8 ^5 V d' A, n' [) I$ Y
//return abc% y* c( f- S; M! |9 j4 H2 _) v
regexp -indices ^abc abcsdfjkhsdf a
: x3 y9 L2 ?9 w/ h8 x# G//return 1' O! ~' i a/ }6 M) a- n
puts $a
g; B, S9 o( Q1 x- @2 X9 [& @" V//return "0 2"9 M9 u0 y u9 t! u
regsub ?switchs? exp string subSpec varName
9 t x$ X3 i; D- a! _1 Q) \, H执行正则表达式的替换,用subSpec的内容替换string中匹配exp的部分。
9 p0 l+ ^0 S3 k' o?switchs? -all 将所有匹配的部分替换,缺省子替换第一个,返回值为替换的个数。( ]- r/ u% Q* B* W; U% s0 k+ f( D
-nocase 不区分大小写。
1 A7 m$ b. h6 }$ \( }2 X如:
6 Z% ~8 }2 d) oregsub abc abcabcbac eee b0 z- E/ n, \$ X- h$ r5 j
//return 1
8 C7 [; W1 j0 [; Kputs $b; w2 j" L7 Z; `8 x# V) N
//return "eeeabcabc"; G+ |" \$ ]( R D' h _
regsub -all abc abcabcabc eee b
7 k8 p% h; T% R! U' Y& P2 t: Y//return 3
0 S" o$ A# W+ ?+ h* q, y! Zputs $b
+ @" F+ X. `! H7 e2 q" z: o! D' d//return "eeeeeeeee"0 D8 L4 o$ Y( P" |1 n
return
7 e& @* \% y# j; N立即从当前命令中返回。4 ]' Q( t# U& c0 \: t. X
proc ff {} {
+ I4 s) I, z: [return friday1 @2 h. c# r9 C4 S+ y" G7 a
}% X! v. d0 a2 R! h
set a [ff]
- P" y# r: y) y//a = "friday"
' L# N2 C4 E- m) C& K. Sscan string `format" varname ...' n: s5 p. @0 W, J9 {4 I- E( F& I
从string中安format来读取值到varname。/ b# v& n4 G, Y6 |3 C z, F+ `5 K
seek fileId offset ?origin?8 ] P* J; {8 S; W( v. P, ^- e. v
移动文件指针。
3 ?7 s& u9 y$ T8 l5 Yorigin: start current end
* s2 H4 m6 B( C9 C+ Coffset从哪里开始算起。
3 i' y' ^+ Q7 iset varname ?value?
9 c( a8 G8 ]+ ?6 j( j设置varname用value,或返回varname的值。如果不是在一个proc命令中则生成一个全局
9 z" C# m# O! R5 z/ a' V4 K/ l变量。2 q8 m& R, j/ Q4 N% M- z- y8 c
source fileName# W# ~% e! O x+ A" ^0 P* m' e: H
从filename中读出内容传给Tcl解释起来执行。
! Y5 _/ |, U4 A& fsplit string ?splitChars?
+ L! D4 I4 E I$ C/ a6 u, U4 y将string分裂成列表。缺省以空白为分隔符,也可通过splitChars来设定分隔符2 Z9 ]# O' m. t {5 V
string subcommand arg ...
5 |1 z' [2 i# r( M% Z用于字符串的命令。
( i/ |' Y( U* k& }( i; Lstring compare string1 string23 P& e8 ?2 d8 H$ q- C5 `& M) }
执行字符串的比较,按 C strcmp 的方式。返回 -1, 0, or 1。3 b1 t2 M* A! X& Q" m; V7 }, F7 F
string first string1 string26 X* f8 b0 p# R! {( s# e
在string1种查找string2的定义次出现的位置。未找到返回-1。: n8 ]3 b4 u, q. j+ a% F
string length string
* [8 }' N6 f. t& p i: I返回字符串string的长度。
) y& p6 }" M* j& vstring match pattern string
- b# ]2 ?% W& P判断string是否能匹配pattern。pattern是以shell文件名的统配格式来给出。2 ` D! n1 W- c* G2 N/ |$ e: e
string range string first last
1 x" _$ d/ x1 B& F返回字符串string中从first到last之间的内容。9 X1 B4 Z3 l. ^2 o9 M
string tolower string4 ~2 @" _/ D' F" h( S3 h
将string转换为小写。. e4 G7 D7 U I6 q, q
string toupper string
& h. U- J2 p$ c将string转换为大写。: V% j7 Z2 _# \% r
string trim string+ x) p9 o; B. X7 Z! m: I; t
将string的左右空白去掉。' l: f( c" B1 i' h
string trimleft string
3 y' H5 S% l# F0 R# L0 h+ ^: N8 T将string的左空白去掉。) @1 x3 r6 @; B* ? O4 P4 i) K
string trimright string
4 [) [" k" }9 V8 i- o% z5 l将string的右空白去掉。
) @ V9 A( n+ K# M2 k6 y9 Ztell fileId
. O8 |+ L3 C! b2 o- F返回fileId的文件指针位置。
* |& T+ F) t4 `3 I2 B: [9 _time command
6 s) \8 h- X1 U执行命令,并计算所消耗的时间。
5 Z# v! H/ @- ctime "ls --color"
6 D _8 d. ^2 {some file name
* }' X. n$ ]% `+ B/ `503 microseconds per iteration
" N G" r8 ^: s2 k0 ]& dtrace subcommand
. u! I4 c0 v5 t. utrace subcommand arg ..." k+ e. V) q- Y# e( U3 m+ h* [
监视变量的存储。子命令定义了不少,但目前只实现了virable。0 d4 A+ k5 @/ q7 i
trace variable name ops command
$ n: P5 w. }4 j! h& R0 Ename 为变量的名字。0 d- e) q. _7 J/ w" l& Z6 I
ops 为要监视的操作。
9 v; V; H5 p" ?% e. or 读
, [. q- v# F8 o, x8 hw 写4 N L! m3 t: Y+ F$ S
u unset# |* s8 B' |: I" q5 M
command 条件满足时执行的命令。
( O- T L) I* t: _% `, F2 H以三个参数来执行 name1 name2 ops5 d4 y- c: r# r4 F$ f! n. z
name1时变量的名字。当name1为矢量时,name2为下标,ops为执行的操作。
0 @2 Z2 ^ j% r$ k; g6 v$ @例如:! B% c: m) @, N$ S* B
proc ff {name1 name2 op} {
% x; p; G6 F2 H+ ^5 W+ x: gputs [format "%s %s %s" name1 name2 op]4 w/ Q1 `; z1 u* i* h! v q6 g
}4 ~3 E6 j( o# G) i3 m
set a hhh* {" X7 b( R. _# ~, o, Q& s2 x$ N
trace variable a r {ff}
- p6 \( B9 S9 e. Mputs $a- `+ w9 { R% f
//return "a r hhh"( A+ P9 ^1 i: `6 B0 j5 @, j
unknown cmdName9 J* @" `8 J* u' F. ^* L8 f. K
unknown 并不是 Tcl 的一部分,当 Tcl 发现一条不认识的命令时会看看是否存在 unknown2 y) v% C- h) A9 U3 c d
命令,如果有,则调用它,没有则出错。. c8 G0 m; A/ Z
如:5 w8 S Z8 \0 ^% w# W$ J% x; E
#!/usr/bin/tclsh
6 ]4 J8 T& y! u3 }0 I& X! C. ?proc unknown {cwd args} {
5 Z1 X$ e; Y, j* ?- Qputs $cwd( X( l( b) ^: Y. S" f$ i0 ~5 z
puts $args
3 H& @" W4 ]) ]8 m. F- } p* X6 l}
$ q7 n: R' {& ]1 d4 |/ |//下面是一条错误命令4 y% J0 D8 M9 h
sdfdf sdf sdkhf sdjkfhkasdf jksdhfk" j7 I. q" Z; U6 U' b2 l! ]3 D+ X
//return "sdfdf sdf sdkhf sdjkfhkasdf jksdhfk"
) [; p/ m4 m( {1 m% runset name ...- p: {( M( t& {/ O1 f) B0 ~
删除一个或多个变量(标量或矢量)。- S5 T4 x7 J6 v, S- H
uplevel command ...
/ m; e% |( B& J2 o4 t, ` z" w' M1 \将起参数连接起来(象是在concat中)。最后在由level所指定的上下文中来执行。如果
Q6 _8 U7 J% Z) o* G: [( ]7 Olevel是一个整数,给出了在栈中的距离(是跳到其它的命令环境中来执行)。缺省为1
4 {# U. G3 K6 z1 J( n(即上一层)。) O8 N: R0 ~$ e/ S6 A* K, M
如:
2 _0 n; R( x8 C5 A, d4 ^3 h#!/usr/bin/tcl C5 E6 x; q& |) i
proc ff {} {
& R6 t$ R9 M8 w1 u; y. E( oset a "ff" //设置了局部的a: `/ G! h/ D+ u1 F8 I2 B$ M
-------------------------
4 e# }7 [: [/ Y7 t2 q& C6 V& A# X}
% I" w/ I- u4 s" dset a "global"
. e8 e8 h" W7 x& P7 r' nff
# |* J' e( Y/ S: `puts $a
$ Q2 k9 }& A7 B8 G. t. v% M//return "global") i0 L3 f( e) B! G8 J6 |
再看下一个:- k+ h) F& [3 w
#!/usr/bin/tcl
- N1 S7 O/ W9 a( s( q! \6 v8 A2 [proc ff {} {
! s- Z1 `% P" u2 Suplevel set a "ff" //改变上一级栈中的a' @6 g9 D5 p7 s3 `4 n- N% }% F% O
-------------------------------------
% o( K- H5 w0 l}
4 x0 Z4 d* o1 w# b! Wset a global' W# c( `6 L+ D1 W Q ]; H
ff: } S; m S% f
puts $a
. `6 G% c* m1 c% R: S. i//return "ff"' z, B2 W1 y& \* M: Q6 Y& f
如果level是以#开头后接一个整数,则level指出了在栈中的
! s; ~+ e9 U/ Z5 V2 o) G% x7 l绝对位置。如#0表示了顶层(top-level)。
: ~8 u6 Z% ~) S2 M- Na b c 分别为三个命令,下面是它们之间的调用关系,
: \/ ]. e& \, w# [/ Ktop-level -> a -> b -> c -> uplevel level" D8 f( y, ~+ F5 a( `% h- Y
绝对位置: 0 1 2 38 i" F$ ^: i' v% {
当level为1或#2都是在b的环境中来执行。3或#0都是在 top-level 的环境中来执行。
; S3 F3 s {! S; }* aupvar ?level? otherVar myVar ?otherVar myVar ...?. N4 u- o' i/ r$ m
在不同的栈中为变量建立连接。这里的level与uplevel中的level是同样风格的。# j- I7 }4 e I* n: v2 N, S
例如:
9 D/ U1 S; x ]% ?' H& ^#!/usr/bin/tcl
2 k4 g5 F! {7 l' l$ _# c* rproc ff {name } {
( K) C7 H) B, o; g+ ]& j. V' A' bupvar $name x
, C; M M' ?0 ~& k, k7 s5 Jset x "ff"/ ?# c; D& j6 }3 y& L( V
}
5 H5 y+ B3 S* Y- bset a "global"& i& u1 K+ H5 E; i2 D m R
ff a" |% H: |3 n3 \% ?5 s' o/ _3 o$ g6 z
puts $a
' j/ k3 [; l; [+ Z' a" Z# Y+ h//return "ff"
! O, ~2 I/ u/ `- {1 u/ Zwhile test body. [, p7 F7 |* D% R* t) U0 O: ^
举个例子吧:
& U* w% z, m+ [! H1 Y4 r# H/ oset x 0& K# G' N/ n+ E5 n
while {$x<10} {) Y6 J" Z! ?& }) T9 |
puts "x is $x"' n% T" D+ [* T$ ]! `+ E
incr x
- I1 g" i3 _3 Z2 ^; V}. _6 U- S0 L/ E/ N3 H
Built-in variables 内建的变量
8 o! i7 p: r& p9 h' M6 |. I下名的全局变量是由 Tcl library 自动来管理的。一般是只读的。
, o3 V- B# b. g' S% Z3 D- kenv' D- E# S* S3 |, k
环境变量数组。' F, n) O: k7 k6 b. y( ?2 g% T
如:/ s2 o6 Z. t$ l& X4 T3 [
puts $env(PATH)
8 m6 i ]% b3 _; z: {+ q7 A) v0 S, t// return /bin:/usr/bin:/usr/X11R6/bin
, g& e K# ^7 [* LerrorCode( P, ~/ {7 d b: O3 u% H
当错误发生时保存了一些错误信息。用下列格式来存储:
# G3 Q- U' v: g8 @+ _CHILDKILLED pid sigName msg# Y6 q5 b5 H H/ a" F* b; n, ~$ B
当由于一个信号而被终止时的信息。, r6 L- C/ {6 w! I
CHILDSTATUS pid code/ l$ F4 N( b2 R9 z* s
当一个子程序以非0值退出时的格式。
: _+ Z( j9 x7 m1 ECHILDSUSP pid sigName msg
+ z& ~" h% O7 G- P- I当一个子程序由于一个信号而被终止时的格式。, e- p& U" U% K
NONE i% I9 y$ c) t; y: N+ A3 a, u) O. r. W
错误没有附加信息。( l4 v a9 ~/ S: e. G" A
UNIX errName msg
6 }: _& }: x4 n1 {) _当一个内核调用发生错误时使用的格式。
/ _. y" y" a. A: i9 A6 AerrorInfo8 G* e' ~! e, i) X
包含了一行或多行的信息,描述了错误发生处的程序和信息。
, D; p `: g( C$ sTcl 名字空间
0 V6 `) k+ \, Z6 A& C# E5 v+ f, Mnamespace6 d3 p/ e9 I4 J: x$ {
创建和操纵命令和变量的上下文(content)。
( E; n K; H- a8 q简介: B* G; n4 o% N8 x
一个名字空间是一个命令和变量的集合,通过名字空间的封装来保证他们不会影响其它名字$ b ]9 q' t/ B! G$ V# W R
空间的变量和命令。 Tcl 总是维护了一个全局名字空间 global namespace 包含了所有的2 v$ g8 ]9 W& W9 L h
全局变量和命令。
' w- _1 M* d; Tnamespace eval允许你创建一个新的namespace。
G$ a7 v# U1 S, G例如:
$ S- n7 y1 r6 Q' P& y8 _ H' _; @namespace eval Counter {0 [/ K8 K3 y$ ~3 `% K2 r
namespace export Bump
2 O+ \6 j8 D) r) Q" k8 @variable num 0
& J# |. o( ?: N' S. _proc Bump {} {7 B# [; i; i8 O+ a. @+ [' B
variable num//声明局部变量
9 d4 u( ]3 n1 E1 Nincr num
- D9 z* f/ x, B7 \/ F1 H- A. N% M}
( V4 y, Z6 ^4 r% ^}+ F7 t5 g. k: Z7 f' V% ]
名字空间是动态的,可变的。
2 c. \6 A8 S* ?0 J6 a! \. t# p例如:* W* g5 R6 M0 {9 i% t
namespace eval Counter {7 k _, G/ ` u5 n
variable num 0//初始化
4 @& I H- F# yproc Bump {} {6 l* I. r. J3 |1 q/ J
variable num4 I- l1 X( `: b0 u% `; e
return [incr num]* Z2 N& V; @9 v! g1 S: _5 J
}3 Z7 f" O+ k* f9 H- R
}
# R; S1 @5 w) s! u/ M, i) m+ R//添加了一个过程* N, n+ P' @& p& e2 I$ {) w, w
namespace eval Counter {
* S, Q5 P: s+ [; a7 }7 D. ]' Eproc test {args} {+ y5 ]; z5 ^% b* `: P
return $args# r) d5 l) U* J! ?# o! r
}' x; P. o2 T9 g" \, l
}$ u: O, c* R* G1 n6 W) e
//删除test* h7 p, i: [4 v3 t
namespace eval Counter {2 J$ ?. q( I C
rename test ""5 M" B( `$ R7 f( g# w
}
. w) u# L) Z) i. x8 X5 Z引用:
0 T1 @ B4 ~5 C) [" w2 b, tset Counter::num
) @0 m, m! U) @//return 0
# V, N: @1 [3 g6 k也可以用下面的方式添加:
4 k% k/ w7 r# `2 z( Q2 {6 Lproc Foo::Test {args} {return $args}
a; J# P7 f/ I: [2 Y或在名字空间中移动:
, `5 P5 o1 b; R3 nrename Foo::Test Bar::Test |
|