1. 流程控制
if命令
if命令后跟两个参数:表达式、待执行的Tcl脚本。if命令中的每一个左大括号都必须与它前一个字符同行。
有elseif和else可选子句,使用时与if中第二个参数的右大括号放在同一行。
switch命令
switch命令利用一个给定值与多个模式进行匹配,执行匹配成功的TCL脚本,有两个参数:待检测的值、一个或多个元素对的列表。每个元素对的第一个元素是匹配模式,第二个元素是匹配成功后需要执行的脚本。
switch同样有三种匹配方式-exact(默认,严格的字符串匹配)、-glob(string match命令下的匹配)、-regexp(正则表达式匹配)。匹配方式后的“--”表明选项结束,后为待检测的值。switch命令的列表参数最好放在大括号中,避免变量值换导致错误。
如果switch命令的最后一个模式为default,则当与其他模式都无法匹配值,就会执行default对应的脚本。
如果匹配模式对应的脚本只是一个短划线“-”,那么switch命令就会认为该模式与下一个模式对应的脚本相同,采用此方法可将对应脚本相同的多个不同匹配模式捆绑在一起。
switch命令中的注释只能添加到匹配模式对应的脚本中,否则会报错。
while命令
while循环命令有两个参数:由表达式构成的循环条件、由Tcl脚本构成的循环体。在执行时,while命令先处理表达式,然后根据表达式的结果判断是否执行循环体。如果表达式的值为真(非0、yes或true),则执行循环体。这个过程不断重复,直至表达式的结果为假(0、no或false),返回一个空字符串。
continue和break是循环控制命令,continue命令只结束本次循环,break命令结束整个循环。
for命令
for循环命令有四个参数:初始化变量、包含循环变量的表达式(用于判断循环是否执行)、更新循环变量、由Tcl脚本构成的循环体。for命令先运行第一个参数中的脚本,随后处理第二个参数值的表达式,如果表达式为真,则运行第四个参数中的Tcl脚本,之后执行第三个参数中的脚本进行循环变量的更新,更新完毕后再处理第二个参数中的表达式,不断循环直到表达式的结果为假。
for循环也可以嵌套。
source命令
source命令用于读取一个Tcl文件,并将文件内容作为Tcl脚本运行,只有一个参数指定要读取的文件名,可以用绝对路径指定,也可以用相对路径指定。source 的返回值就是运行文件内容的返回值,即文件中最后一条命令的返回值。
2. 过程
Tcl的过程是由一系列命令构成的代码块,用于执行特定的任务,可分为Tcl自定义的内建(Built-in)过程(如power()、exp()等)和用户定义的过程。过程由命令proc创建,有三个参数:过程名、参数名列表、构成过程块的Tcl脚本,过程块通过return返回该过程的值。
过程的参数名列表和返回值
proc的参数名列表可以为空、一个参数名、多个参数名或参数名的个数为变量。参数名列表支持可变个数的参数,将特殊参数名args放在参数名列表的最后一个,args是一个可变长度的列表。
在创建过程中,Tcl允许给参数设置默认值,但要求带默认值的参数名与对应的参数值出现在参数名列表的最后位置,除非最后一个参数名为args。参数名在参数名列表里的顺序为无默认值的参数名、带默认值的参数名和特殊参数名args。
当过程中没有使用return命令,返回值为过程块中最后一条命令的返回值;如果使用了return,返回值由return决定,并且可以将返回的多个值放在列表中,以列表的形式返回。
局部变量与全局变量
局部变量是过程块中定义的变量,其作用域仅限于过程块内,生命周期随着过程的返回而结束;全局变量是过程之外定义的变量,它们长期存在,仅在明确被删除后才消失。不同过程块中的局部变量可以有相同的变量名,局部变量也可以和全局变量同名,但它们是不同的变量。
如果需要在过程中使用全局变量,则可以使用global命令实现。该命令会把它的第一个参数作为全局变量的名称,从而将过程中对这些变量名的引用定向到全局变量。可以在过程中的任何时候调用global命令,一旦调用,就会一直生效,直到过程返回。
如果需要在过程块中使用全局变量,则建议将变量名用大写字母的方式命名。
upvar命令
模拟引用
全局变量可通过局部变量的引用来更新,用到命令upvar,有两个参数:全局变量名、局部变量名,即局部变量将引用全局变量。
数组用作参数或返回值
upvar命令可以将数组名传递给过程,使得在过程中可以访问数组或返回数组
给变量起别名
3. 命名空间
创建命令空间
命名空间是变量和过程的集合,使得Tcl能对这些变量和过程进行分组管理。不同的命名空间中同名变量或过程是相互独立的。
命令namespace eval用于创建命名空间,有两个参数:命名空间名、命名空间内容(命名空间变量和过程)。过程也可以在命名空间外定义,但是需要在过程名前使用命名空间分隔符(::),表明该过程属于哪个命名空间,也可以用命名空间分隔符访问变量和过程。
命名空间可以嵌套,在已有的命名空间下再次创建命名空间。
命名空间为树状结构,根为全局命名空间,直接以::开头访问的是全局命名空间。
命令namespace children可返回指定命名空间的子空间,命令namespace parent可返回指定命名空间的父空间。命令namespace exists用于确定指定命名空间是否存在,存在返回1、否则返回0。命令namespace qualifiers后跟随一个参数,可返回该参数中最后一个命令分隔符之前的所有字符。命令namespace tail后跟随一个参数,可返回该参数中最后一个命令分隔符之后的所有字符。命令namespace delete删除全局命名空间中已存在的子命名空间。
创建命令空间变量及作用域
命令variable可创建命名空间变量并对其初始化,同时可使命名空间中的过程访问该变量。
命令variable可将数组设置为命名空间变量,但不能对其进行初始化,需要用array set进行初始化,也可使数组对过程可见。
命名空间变量的作用域仅限于对其定义的命名空间,并且全局变量、命名空间变量和局部变量可以同名。对于嵌套的命名空间,命名空间变量也不可向下传递。
访问命令空间变量
有三种方法访问命名空间变量:
1.通过命名空间分隔符访问并改变其初始值
2.通过命令upvar引用命名空间变量,给其起别名,并通过给别名赋值的方式改变命名空间变量的值
3.命令namespcae upvar给用命名空间变量,有三个参数:命名空间名、该命名空间中的变量名、给该命令空间变量的别名
命令namespace还可以使一个命名空间引用另一个命名空间的变量。
从命令空间导入和导出命令
命令namespace export可将命令空间中的命令导出,命令namespace可将命令空间中的命令导入。
命令namespace forget可以遗忘已经导出的命令;命令info command可用于查询指定命名空间包含的所有命令;命令namespace origin可用于查询导入命令的原始来源。
创建集合命令
通过命令namespace ensemble create创建集合命令,创建后在使用时可以不用再添加分隔符,还可以使用缩写形式,只要缩写后的命令对应的完整命令是唯一的。
4. 访问文件
操纵文件名和目录名
对于文件目录,Windows系统采样反斜线、Linux系统采用正斜线,为了避免Tcl中的反斜线替换,因此在Windows系统使用Tcl时统一使用正斜线作为文件目录分隔符。
Tcl中的file是一个包含多个选项的通用命令,file dirnmae返回文件名路径;file extension返回文件拓展名;file nativename返回原生格式的文件名;file rootname返回除拓展名之外的部分;file tail返回文件的最后一个部分,即最后一个子目录下的文件名;file split可将文件名安正斜线"/"所在位置进行分割并返回各部分字符串;file join是file split的逆过程。
当前工作目录和目录内容
Tcl支持文件的绝对路径和相对路径,pwd(print working directory)不需要任何参数,返回当前目录的绝对路径;cd(change directory)有一个参数,将当前目录切换到该参数指定的目录;glob获取当前工作目录下的内容,该命令后跟随一个或多个模式参数,返回与这些模式匹配的文件夹或文件名列表。
glob可以跟随选项-types,-types的可选值有多种,如d和f。d表示目标(文件夹),f表示文件。对于文件还可以提供访问授权标志:r表示读取授权,w表示写入收起,x表示执行授权,hidden表示隐藏一级文件,readonly表示只读授权。
处理磁盘上的文件
命令file mkdir(make directory)可在当前工作目录下创建一个新的目录,该目录的名字由file mkdir之后的参数决定,如果指定目录名称已经存在,则命令不会进行任何操作,也不会返回任何错误信息。
命令file delete用于删除指定的文件或目录,如果目录为空,则file delete就会产生错误信息,可添加-forece选项删除非空目录。
命令file copy将源文件复制到目标文件,有两个参数:源文件名称、目标文件名称,如果目标文件已存在就会报错,可使用-force覆盖已存在的目标文件。file copy还可以将指定的多个文件复制到目标目录中。
命令file rename可将指定的文件或目录重命名,有两个参数:源文件或源目录名、目标文件或目标目录名称,如果目标名称已存在,则会报错,可通过-force覆盖已存在的文件。如果目标名称指向了另一个目录,则file rename会把文件移动到新目录下。
获取文件信息
Tcl提供了一些命令获取文件信息,格式通常为file option name,file exists查看指定的文件或目录是否存在,存在为1否则为0;file isfile判断指定的内容是否为文件,是为1否为0;file isdirectory判断指定的内容是否为目录,是为1否为0;file type查看指定内容的类型,返回值根据内容的不同可分为file、directory、socket;file readable、writable、executable,当指定文件存在且当前用于有执行指定操作的权限时返回1,否则返回0;file stat可一次性得到文件的各种信息,有两个参数:指定的文件名或目录名、数组(用于存储文件信息)。
选项stat可一次性得到文件的各种信息,有两个参数:指定的文件名或目录名、一个数组(用于存储文件信息)
关键字 | 值 |
atime | 最后一次被访问的时间 |
ctime | 最后一次改变状态的时间 |
dev | 文件的群组识别符 |
gid | 文件在设备中的序列号 |
ino | 文件在设备中的序列号 |
mode | 文件模式位 |
mtime | 最后一次被修改的时间 |
nlink | 链接到文件的链接数量 |
size | 文件大小,单位为字节 |
uid | 拥有文件的用户标识 |
type | 根据给定的文件名返回文件类型 |
文件的读写
Tcl可通过命令open打开一个文件,有两个参数:文件名、访问模式,返回值是给定文件的文件描述符,可被其他命令使用。
访问模式 | 含义 |
r | 只读模式。指定文件必须存在。如果不指定访问模式,则此模式为默认模式。 |
r+ | 可读写模式。指定文件必须存在。 |
w | 只写模式。如果文件存在,则删除文件中的全部内容;如果文件不存在,则创建一个空的文件夹。 |
w+ | 可读写模式。如果文件存在,则删除文件中的全部内容;如果文件不存在,则创建一个空的文件夹。 |
a | 只写模式。将初始访问位置设为文件尾,故新写入的内容将添加到文件原有位置后,除非重新设置了访问位置。如果文件不存在,则创建一个空的文件夹。 |
a+ | 可读写模式。将初始访问位置设为文件尾,故新写入的内容将添加到文件原有位置后,除非重新设置了访问位置。如果文件不存在,则创建一个空的文件夹。 |
命令read读取文件,有一个或两个参数:open命令的返回值、读取量(以字节为单位),两个参数时用于获得文件大小。
命令close关闭已打开的文件,其后跟随open命令的返回值。
read是按块操作,当文件较大时,会占用较大的存储空间,因此Tcl还有按行读取文件内容的方式。命令gets有两个参数:open命令的返回值、用于存储文件行内容的变量,返回值为改行内容的大小(以字节为单位),当读到文件末尾时,gets返回-1。gets一个参数:open命令的返回值,此时返回获取文件的行内容。
命令eof(End of File),一旦读取到文件末尾,返回1。
命令puts向文件中写入数据,有两个参数:open命令的返回值、待写入的数据,可用-nonewline阻止换行。
处理CSV文件
CSV(Comma-Separated Values,字符分隔值)文件是一种以纯文本形式存储表格数组的文件。纯文本意味着该文件是一个字符序列,由任意多个记录组成,记录间以换行符分割;记录由字段组成,字段之间通常以逗号作为分隔符。
Tcl提供了处理CSV文件的包:
命令csv::split后跟随一行CSV格式的内容,可指定分隔符,在未指定分隔符的情况下,默认分隔符为逗号。
命令csv::read2matrix将CSV文件中的内容读入到指定到指定的矩阵中,通过对矩阵进行行操作一次读取每行的内容。
命令csv::read2queue可将CSV文件中的内容读入到一个队列中,每一行内容构成队列中的一个元素,利用队列先入先出的特性从中取出这些元素,直到队列为空,实现对CSV文件每行内容进行处理的功能。
命令csv::join实现以CSV格式写入数据并生成CSV文件的目的,命令后跟随一个列表(被认为是CSV的一行内容),默认的分隔符是逗号,也可指定分隔符。
命令csv::joinlist完成写CSV文件操作,命令后跟随一个列表,此列表通常是一个嵌套列表,每个子列表构成CSV文件的一行内容。