本章描述了一个允许您查询和操纵TCL解释器内部状态的命令集.例如,您可以通过这些命令看一个变量是否存在,可以查看数组有哪些入口(entry),监控所有对变量的访问操作,可以重命名和删除一个命令或处理那些未定义命令的参考信息.
11.1查询数组中的元素利用array命令可以查询一个数组变量中已经定义了的元素的信息.array命令的形式如下:
arrayoptionarrayName?argarg...?
由于option的不同,array命令有多种形式.如果我们打算开始对一个数组的元素进行查询,我们可以先启动一个搜索(search),这可以由下面的命令做到:
arraystartseracharrayName:这个命令初始化一个对name数组的所有元素的搜索(search),返回一个搜索标识(searchidentifier),这个搜索标识将被用于命令arraynextelement,arrayanymore和arraydonesearch.
arraynextelementarrayNamesearchId:这个命令返回arrayName的下一个元素,如果arrayName的所有元素在这一次搜索中都已经返回,那么返回一个空字符串.搜索标识searchId必须是arraystartserach的返回值.注意:如果对arrayName的元素进行了添加或删除,那么所有的搜索都会自动结束,就象调用了命令arraydonesearch一样,这样会导致arraynextelement操作失败.
arrayanymorearrayNamesearchId:如果在一个搜索中还有元素就返回1,否则返回0.searchId同上.这个命令对具有名字为空的元素的数组尤其有用,因为这时从arraynextelement中不能确定一个搜索是否完成.
arraydonesearcharrayNamesearchId:这个命令中止一个搜索,并销毁和这个搜索有关的所有状态.searchId同上.命令返回值为一个空字符串.当一个搜索完成时一定要注意调用这个命令.
array命令的其他option如下:
arrayexistsarrayName:如果存在一个名为arrayName的数组,返回1,否则返回0.
arraygetarrayName?pattern?:这个命令的返回值是一个元素个数为偶数的的list.我们可以从前到后把相邻的两个元素分成一个个数据对,那么,每个数据对的第一个元素是arrayName中元素的名字,数据对的第二个元素是该数据元素的值.数据对的顺序没有规律.如果没有pattern参数,那么数组的所有元素都包含在结果中,如果有pattern参数,那么只有名字和pattern匹配(用stringmatch的匹配规则)的元素包含在结果中.如果arrayName不是一个数组变量的名字或者数组中没有元素,那么返回一个空list.例:
%setb(first)11%setb(second)22%arraygetbsecond2first1
arraysetarrayNamelist:设置数组arrayName的元素的值.list的形式和arrayget的返回值的list形式一样.如果arrayName不存在,那么生成arrayName.例:
%arrayseta{first1second2}%puts$a(first)1%arraygetasecond2first1
arraynamesarrayName?pattern?:这个命令返回数组arrayName中和模式pattern匹配的元素的名字组成的一个list.如果没有pattern参数,那么返回所有元素.如果数组中没有匹配的元素或者arrayName不是一个数组的名字,返回一个空字符串.
arraysizearrayName:返回代表数组元素个数的一个十进制的字符串,如果arrayName不是一个数组的名字,那么返回0.
下面这个例子通过使用arraynames和foreach命令,枚举了数组所有的元素:
foreachi[arraynamesa]{puts"a($i)=$a($i)"}
当然,我们也可以利用startsearch,anymore,nextelement和donesearch选项来遍历一个数组.这种方法比上面所给出的foreach方法的效率更高,不过要麻烦得多,因此不常用.
11.2info命令info命令提供了查看TCL解释器信息的手段,它有超过一打的选项,详细说明请参考下面几节.
11.2.1变量信息info命令的几个选项提供了查看变量信息的手段.
infoexistsvarName:如果名为varName的变量在当前上下文(作为全局或局部变量)存在,返回1,否则返回0.
infoglobals?pattern?:如果没有pattern参数,那么返回包含所有全局变量名字的一个list.如果有pattern参数,就只返回那些和pattern匹配的全局变量(匹配的方式和stringmatch相同).
infolocals?pattern?:如果没有pattern参数,那么返回包含所有局部变量(包括当前过程的参数)名字的一个list,global和upvar命令定义的变量将不返回.如果有pattern参数,就只返回那些和pattern匹配的局部变量(匹配的方式和stringmatch相同).
infovars?pattern?:如果没有pattern参数,那么返回包括局部变量和可见的全局变量的名字的一个list.如果有pattern参数,就只返回和模式pattern匹配的局部变量和可见全局变量.模式中可以用namespace来限定范围,如:foo::option*,就只返回namespace中和option*匹配的局部和全局变量.(注:tcl80以后引入了namespace概念,不过我们一般编写较小的TCL程序,可以对namespace不予理睬,用兴趣的话可以查找相关资料.)
下面针对上述命令举例,假设存在全局变量global1和global2,并且有下列的过程存在:
proctest{arg1arg2}{globalglobal1setlocal11setlocal22…}
然后在过程中执行下列命令:
%infovarsglobal1arg1arg2local2local1//global2不可见%infoglobalsglobal2global1%infolocalsarg1arg2local2local1%infovarsalglobal1local2local.2.2过程信息
info命令的另外的一些选项可以查看过程信息.
infoprocs?pattern?:如果没有pattern参数,命令返回当前namespace中定义的所有过程的名字.如果有pattern参数,就只返回那些和pattern匹配的过程的名字(匹配的方式和stringmatch相同).
infobodyprocname:返回过程procname的过程体.procname必须是一个TCL过程.
infoargsprocname:返回包含过程procname的所有参数的名字的一个list.procname必须是一个TCL过程.
infodefaultprocnameargvarname:procname必须是一个TCL过程,arg必须是这个过程的一个变量.如果arg没有缺省值,命令返回0;否则返回1,并且把arg的缺省值赋给变量varname.
infolevel?number?:如果没有number参数,这个命令返回当前过程在调用栈的位置.如果有number参数,那么返回的是包含在调用栈的位置为number的过程的过程名及其参数的一个list.
下面针对上述命令举例:
procmaybeprint{ab{c24}}{if{$a$b}{putsstdout"cis$c"}}%infobodymaybeprintif{$a$b}{putsstdout"cis$c"}%infoargsmaybeprintabc%infodefaultmaybeprintax0%infodefaultmaybeprintac1%setx24
下面的过程打印出了当前的调用栈,并显示了每一个活动过程名字和参数:
procprintStack{}{setlevel[infolevel]for{seti1}{$i$level}{incri}{puts"Level$i:[infolevel$i]"}}11.2.3命令信息
info命令的另外选项可以查看命令信息.