Tcl脚本初步学习
2018-03-09 20:37
183 查看
1.命令
Tcl是一门基于命令的脚本语言,每个命令通过换行符或分好隔开。每条命令都包含一个或多个单词,第一个单词是命令名,其他单词是命令的参数,如:命令 | 命令名 | 参数 |
set a 15 | set | a、15 |
proc power {base p} { set result 1 while {$p > 0} { set result [expr $result*$base] set p [expr $p-1] } return $result } | proc | power、{base p}、 { set result 1 while {$p > 0} { set result [expr $result*$base] set p [expr $p-1] } return $result } |
set result [expr $result*$base] | set | result、 [expr $result*$base] |
power 2 6 | power | 2、6 |
在命令中,每个参数用空格隔开,要注意双引号、中括号和大括号里的内容整体作为一个参数。
在Tcl执行过程中,先解析命令,然后把参数作为这个命令的输入,执行命令时再由命令进一步解析参数。
2.替换
Tcl解析时会把命令分解为单词,然后根据相应的规则对这些单词执行替换操作。Tcl提供了3种形式的替换:变量替换、命令替换和反斜杠替换。 | 符号 | 举例 | 替换 |
变量替换 | $ | set a 15 expr $a*2.2 | 把$a替换为15 |
命令替换 | [] | set b [expr 13*13] | 方括号内的单词必须构成有效的Tcl脚本,里面的内容会替换为执行脚本后的返回值 |
反斜杠替换 | \ | set a bbb\ \$aa\x31 | 把“\ ”“\$”“\x31” 替换成字符空格、$、1。空格和$有特殊意义,所有要使用该字符要进行替换,\x31是把ascii码替换为字符 |
3.引用
Tcl提供了引用的方法,来阻止解释器对一些特殊字符做特殊处理。引用的方法有2种,分别是双引号引用和大括号引用。● 双引号引用
在双引号引用中,空格、制表符、换行以及分号都做普通字符处理,如:
set msg "Eggs: \$2.18/dozen
Gasoline: \$1.49/gallon"
此时输出为:
Eggs: $2.18/dozen
Gasoline: $1.49/gallon
这里面的空格和换行符做为普通字符处理,但是仍然执行替换操作。
● 大括号引用
大括号提供了更彻底的引用形式,它会取消其中所有特殊字符的特殊意义。在大括号里的所有内容都表现为最原始的字符串,不会有任何替换,如:
set a 15
set b {$a}
此时第二行输出是$a而不是15
4.对象
4.1对象的定义
Tcl里没有专门的变量定义,变量的外在表现形式为e7c4
$替换操作,内在表现形式为对象。
由set命令来定义一个对象,在Tcl里所有的对象都当作字符串来处理,以下举一些例子来理解Tcl中的对象:
set 123 abc
这里123是一个对象,它的值是abc
set abc 123
这里abc是一个对象,它的值是字符串“123”,不是数字123
特别要指出的是Tcl里的字符串一般都是指的是普通字符串(以\0结尾的),但是有时候还可以是二进制字符串,如
set a“abc\000123”,它的值是abc
123而不是abc
虽然所有的对象都是基于字符串,但是当把对象作为参数传给命令时,命令可以对其做出其他解释,比如
set a 111
set b 222
expr $a+$b
这里expr命令把对象a和对象b被解释为了数字。
命令执行后会返回一个对象
set c [expr $a+$b]
这里expr $a+$执行完后返回一个对象,这个对象的值是333,并把对象c的值设为333
4.1对象的结构
对象的结构体定义如下typedef struct Tcl_Obj { int refCount; /* When 0 the object will be freed. */ char *bytes; /* This points to the first byte of the * object's string representation. The array * must be followed by a null byte (i.e., at * offset length) but may also contain * embedded null characters. The array's * storage is allocated by ckalloc. NULL means * the string rep is invalid and must be * regenerated from the internal rep. Clients * should use Tcl_GetStringFromObj or * Tcl_GetString to get a pointer to the byte * array as a readonly value. */ int length; /* The number of bytes at *bytes, not * including the terminating null. */ const Tcl_ObjType *typePtr; /* Denotes the object's type. Always * corresponds to the type of the object's * internal rep. NULL indicates the object has * no internal rep (has no type). */ union { /* The internal representation: */ long longValue; /* - an long integer value. */ double doubleValue; /* - a double-precision floating value. */ void *otherValuePtr; /* - another, type-specific value. */ Tcl_WideInt wideValue; /* - a long long value. */ struct { /* - internal rep as two pointers. */ void *ptr1; void *ptr2; } twoPtrValue; struct { /* - internal rep as a pointer and a long, * the main use of which is a bignum's * tightly packed fields, where the alloc, * used and signum flags are packed into a * single word with everything else hung * off the pointer. */ void *ptr; unsigned long value; } ptrAndLongRep; } internalRep; } Tcl_Obj;
成员bytes是一个char*指针,用来存储字符串,length表示bytes存储的字符串的长度。
成员const Tcl_ObjType *typePtr定义了一个对象的类型,这些类型有string、int、bytearray等等,默认的是tclEmptyString类型,即为null,当作二进制字符串处理。因为一个对象有不同的类型,这就解释了为什么对象是字符串,却可以被解释为数字或数组。
假如定义一个对象Tcl_Obj *objPtr,对象被解释为数组,那么由Tcl_SetByteArrayObj()函数可以设置这个对象的数组长度,并把传入数组的内容复制到这个对象的数组里,代码如下
#define SET_BYTEARRAY(objPtr, baPtr) \ (objPtr)->internalRep.twoPtrValue.ptr1 = (void *) (baPtr) void Tcl_SetByteArrayObj( Tcl_Obj *objPtr, /* Object to initialize as a ByteArray. */ const unsigned char *bytes, /* The array of bytes to use as the new value. May be NULL even if length > 0. */ int length) /* Length of the array of bytes, which must be >= 0. */ { ByteArray *byteArrayPtr; if (Tcl_IsShared(objPtr)) { Tcl_Panic("%s called with shared object", "Tcl_SetByteArrayObj"); } TclFreeIntRep(objPtr); TclInvalidateStringRep(objPtr); if (length < 0) { length = 0; } byteArrayPtr = ckalloc(BYTEARRAY_SIZE(length)); byteArrayPtr->used = length;//设置数组的长度 byteArrayPtr->allocated = length; if ((bytes != NULL) && (length > 0)) { memcpy(byteArrayPtr->bytes, bytes, (size_t) length);//复制二进制字符串的内容 } objPtr->typePtr = &properByteArrayType; SET_BYTEARRAY(objPtr, byteArrayPtr);//把数组关联到对象里 }
在通过Tcl的API自定义命令时,可以通过Tcl_SetObjResult()来设置返回的对象。
5. binary命令
之前自己对binary scan和binaryformat这2个命令存在疑惑,有了上面这些基础总算完全明白这2个命令了。
5.1 binary format
binary format命令是把参数按照一定格式转换为二进制字符串,并返回二进制字符串,格式类型可以查看官方的说明文档,使用如下binary formatformatString ?arg arg ...?
举例:
binary format a7a*a alpha bravo charlie
返回二进制字符串alpha\000\000bravoc
其中a代表的类型为unicode码,7代表第一个参数要转换的个数,而alpha中只有5个字符,不足的补0。第二个参数转换的类型为a*表示全部字符都转换。第3个参数类型为a,没有指定要转换的个数,那么默认只转第1个字符。
binary format i3 {3 -3 65536 1}
返回\x03\x00\x00\x00\xfd\xff\xff\xff\x00\x00\x01\x00
其中类型是小端的32位有符号整数,指定为第一个参数的前3个数字。
5.2 binary scan
与binary format相反,binaryscan是把一个二进制字符串按一定的格式输出到指定的变量,并返回设置的变量的个数,使用如下
binary scanstring formatString ?varName varName ...?
举例:
set str \x05\x00\x00\x00\x07\x00\x00\x00\xf0\xff\xff\xff
binary scan $str i2i* var1 var2
返回2,var1的值是57,var2的值是-16
binary scan abcde\000fghi a6a10 var1 var2
返回1,var1的值是abcde\000,由于字符个数不够,并没有设置var2
5.3使用的对象
binary format命令返回一个二进制字符串对象,这个对象的类型是什么呢,binary scan使用的二进制字符串对象的类型又是什么呢?经过调试,objPtr->typePtr的类型既不为string类型也不为空,而是bytearray,即对象实际上是一个数组,这数组里存放着二进制字符串,数组的长度指定二进制字符串的长度。
一般定义一个简单的对象,如
set a 123
对象a的类型是空即tclEmptyString类型,默认是一个字符串,当a被expr命令调用时,a的类型会被转换为int,被binary scan命令调用时,a会被转换为bytearray类型而不是string类型。
相关文章推荐
- TCL脚本语言学习
- 2.TCL脚本学习——Tk入门基础
- FPGA学习笔记6-Quartus II中的TCL脚本(翻译)
- Shell脚本初步学习-鸟哥Linux私房菜基础学习篇
- Linux shell脚本学习初步
- TCL脚本学习笔记1(原创)
- ns2相关学习——TCL脚本编写(3)
- TCL脚本学习
- shell学习笔记三--脚本初步
- TCL脚本语言学习
- TCL脚本语言学习
- ns2相关学习——TCL脚本编写(2)
- TCL脚本语言学习
- FPGA学习之TCL自动化测试脚本
- TCL脚本学习笔记
- shell脚本和vim模式初步学习
- Unity学习笔记——Unity基础四:刚体及脚本初步
- ns2相关学习——tcl脚本编写(1)
- TCL 脚本学习的好资料
- TCL脚本学习