要编写Tcl脚本,必须学会两件事。第一:学会Tcl的语法。第二掌握在脚本中的独立命令。

脚本,命令和单词

Tcl脚本包含一条或更多的命令。命令通过换行符或分号隔开。每一条命令都包含一个或多个单词,第一个单词是命令名,其他的单词是命令的参数。

set a 1
set b 2set a 1 ;set b 2

上述代码可以两行表示,也可以用换行符隔开,一行表示。

处理命令

Tcl处理一个命令分为两步:解析和执行。具体的Tcl处理一条命令的步骤见下图。

在解析这一步,Tcl解释器将命令分解为单词,并执行替换。对每个命令进行解析的方法是一样的。在解析阶段,Tcl解释器不认为各单词的值有任何具体意义。Tcl只是进行一系列简单的字符串操作。

执行阶段,命令中的每个单词都有了具体的意义。Tcl把第一个单词作为命令名称,检查此命令是否存在或者被定义过,并且查找完成该命令功能的命令过程。

双引号引用

双引号取消其中的单词和命令分隔符的特殊解释。如果一个单词的第一个字符是双引号,那么这个单词就由另一个双引号标记结束。双引号并不是单词的一部分,而是此单词的定界符而已。如果一个单词包含在双引号中,那么其中的空格,制表符,换行以及分号都作为普通字符处理。

如果单词不是以双引号开头,那么单词中的双引号就会被当成普通字符处理,而不是定界符。

在双引号中,变量替换,命令替换以及反斜线替换正常工作。如果想要在由双引号括起来的单词中包含双引号字符,则应该使用反斜线替换。

大括号引用

大括号提供了更彻底的引用形式,它会取消其中所有特殊字符的特殊意义。如果从一个单词以左大括号开头,那么直到与它配对的右大括号为止,所有字符都将被原封不动地识别为这个单词的值。

和双引号不同,大括号可以嵌套使用。在过程定义和命令流控制中。经常会用到嵌套的大括号来把一个或多个参数表达为需要处理的脚本。大括号最重要的应用之一就是“延期处理”。延期处理意味着特殊字符不会被Tcl解析器立即处理,作为参数传递给命令过程。 例如下面这个过程,它统计在列表中某个特定值出现的次数。

整个过程块都括在大括号中,它会原封不动地传递给proc。在解析proc命令时变量list的值不会被替换进来。正常工作时,在每次调用这个过程时$list都需要读入不同的值。

下面将演示这句Tcl脚本运行时会发生什么,如下图所示:

occur的第二个参数由大括号引用,这会把整个数字列表作为一个单词传给occur。Tcl过程管理机制又会把整个过程块传给Tcl解释器进行处理。在Tcl解析该过程块中的foreach命令时,变量list的值就会替换进来,但这时foreach的最后一个参数(循环体)还在一个大括号当中,此时不会进行替换。foreach命令过程会把变量el依次赋值为列表中的命令,替换变量el和value的值。在上图中,if判断通过,处理incr命令。

参数展开

通常来说,列表的值可能是变量或命令替换的结果。但是因为Tcl解释器是从左向右进行替换的,而列表的值被视为一个单词,即列表中嵌入的空格不会被视为单词分隔符。在某些情况下,单层替换规则有害无益。这个脚本就不能删除所有以.o结尾的文件的任务。

file delete [golb *.o]

glob命令返回的是符合*.o形式的文件名列表。例如a.o b.o c.o。然而,在整个文件名称列表中是作为一个参数传递给file delete的,file delete会因为找不到名为a.o b.o c.o的文件而失败。想要file delete正常工作,可以通过参数展开来完成这一任务。如果一个单词以字符串{*}开头,之后紧接着非空白字符,Tcl会移除开头的{*},把该单词的剩余部分作为含有单词分隔符的语句进行解析与替换。在替换之后,Tcl会再此解析这些单词,但不进行替换,校验确定它们的确是一个或多个语法完整的单词。如果校验通过,这些单词会被独立地加入命令行进行处理;否则,Tcl会报语法错误。因此,下面两条语句是相同的。并且可以使用eval命令解决刚才file delete遇到的问题。

file delete {*}[glob *.o]
#由Tcl解释器进行解析和参数展开后,与下面这条语句相同:
file delete a.o b.o c.o
#或者使用eval命令解决file delete的问题
eval file delete [glob *.o]

注释

如果一条命令的第一个非空白字符是#,那么这一行将视为注释而忽略。注意注释符必须出现在Tcl预期将获得命令的第一个字符的位置上。如果注释符出现在其他地方,会被看作一个普通字符,看成一个命令单词的一部分。

#This is a comment
set a 100
wrong #args:should be "set varName ?newValue?"
set b 101     ;#This is a comment

第二行的符号#就没有被视为注释符,因为它出现在一条命令的中间。其结果是,第一个命令set接收到6个参数,产生了错误。最后一个#被视为注释符,因为它紧接在标记一条命令中止的分号后面。Tcl的语法虽然简单而统一,但也产生一些意料之外的结果。它要求作为注释符的#必须出现在预期将获得命令的第一个字符的位置上,这就导致下面这个示例中的#行不是注释。

set example {#This is not a comment
}

大括号之间的所有字符都视为一个参数处理,作为字符串值赋给set指定的变量,相反,考虑下面这个示例:

if {$x < 0} {#This is a comment
puts "The result is negative."
}

这里,Tcl解析器把两个大括号里的内容作为两个参数传递给if命令。if命令会把第一个参数视为布尔型表达式处理,如果结果为真,它就调用Tcl解释器将第二个参数作为Tcl脚本处理。在Tcl解释器再次进行解析时,以#开头的这一行才被识别注释。Tcl的一致语法引起另一个后果是,在运行代码时,出现注释中的大括号常常会导致错误。参考下面这个示例:

proc countdown {x} {
puts "Running countdown"
#Incorrectly comment out this code block {while {$x >=0} {puts "x =$x"incr x -1}}
}

当Tcl解释器解析这个命令时,第一行末尾的左大括号标记着一个单词的开始。标记单词结束的右大括号出现在最后一行。这个单词中包含着什么脚本与这一步解析无关,Tcl解释器出现只是把命令行解析为单词集,对单词中嵌套的其他大括号只作为普通字符对待。然后Tcl将单词传递给proc命令,该命令会把这些单词作为countdown过程的实现脚本存储。试图运行countdown过程时,Tcl解析并运行这个脚本。首先执行puts命令,然后Tcl忽略整个第二行(包含左大括号),将其视为注释。然后处理while命令,它的脚本参数由incr命令后面那个右大括号标记结束。然后Tcl期待找到下一条命令,却在该行开头取到右大括号,它将这个右大括号视为要处理的命令名,结果导致如下错误:

countdown 3
#开始运行countdown过程
Running countdown
x    =    3
x    =    2
x    =    1
x    =    0
#将运行到x=0;就会跳出while循环块,将获得一个新的命令incr后的右大括号
#右大括号视为处理的命令,结果会导致错误
invalid command name "}"

Notes:一般来说,尽量避免在注释中出现大括号,如果确实需要在注释中使用大括号,确保它们时配对的;对于每一个左大括号,都保证有一个正确匹配的右括号。

正常返回和异常返回

Tcl命令可能以多种方式完成。正常返回时最常见的结果,这意味着 命令正常执行完成,返回一个字符串值。Tcl还支持命令的异常返回。错误是异常返回的最常见形式。当错误返回时,就意味着命令未能按照所期望的功能执行。该命令被放弃,它后面的脚本中的命令被略过。

Tcl替换机制

1.Tcl解析一条命令时,只从左向右解析一次,进行一轮替换。每一个字符只会被扫描一次。

2.每一个字符只会发生一层替换,而不会对替换后的结果再进行一次扫描替换。

TCL学习心得(2)Tcl语言的语法相关推荐

  1. [编译原理学习笔记2-2] 程序语言的语法描述

    [编译原理学习笔记2-2] 程序语言的语法描述 文章目录 [编译原理学习笔记2-2] 程序语言的语法描述 [2.3.1] 上下文无关文法 [2.3.2] 语法分析树与二义性 [2.3.3] 形式语言鸟 ...

  2. 河南师范大学python+学习笔记2 python语言基本语法元素

    吃水不忘挖井人 首先对河南师范大学的各位老师们说声谢谢.他们是: 张磊老师.张倩倩老师.刘金金老师.郭凌云老师.李晓艳老师.李志先老师.陶华亭老师.周雪燕老师.王爱菊老师.陈劲松老师.黄晓巧老师.夏辉 ...

  3. MYSQL收获及体会_我的MYSQL学习心得(一) 简单语法

    语法的差异 我这里主要说语法的不同 1.默认约束 区别:mysql里面DEFAULT关键字后面是不用加括号的 --sqlserver CREATE TABLE emp ( id INT DEFAULT ...

  4. c语言入门报告,c语言学习心得报告

    c语言学习心得报告 C 语言学习心得报告 看了一段时间的<C和指针> ,这样看的效果不是很好,看着书本当时是懂 了,有点恍然大悟的感觉,但是发现并不能真正的把理解的内容加入到自己程 序当中 ...

  5. 我的MYSQL学习心得(十六) 优化

    原文:我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(十六) 优化 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看 ...

  6. 我的MYSQL学习心得(十一) 视图

    我的MYSQL学习心得(十一) 视图 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三) 查看字段长度 我的MYSQL学习心得(四) 数据 ...

  7. MYSQL学习心得 总结

    http://www.cnblogs.com/lyhabc/p/3691555.html 我的MYSQL学习心得(一) 简单语法 我的MYSQL学习心得(二) 数据类型宽度 我的MYSQL学习心得(三 ...

  8. golang学习笔记之--Go语言内建容器

    话接上文 <golang学习笔记之--Go语言基本语法> 今天继续记录学习笔记,今天的笔记主题是Go语言内建容器 如果各位童鞋想要获得下面的源码,请搜索gzh:隔壁王小猿,关注后回复&qu ...

  9. TCL学习--语法置换(第一篇)

    文章目录 一.TCL语法 1.脚本.命令和单词符号 2.置换 (a)变量置换 (b)命令置换 (c) 反斜杠置换 (d)双引号和花括号 3.注释 一.TCL语法 TCL是一种解释脚本执行的脚本语言,提 ...

  10. [转]verilog语法学习心得

    verilog语法学习心得 1.数字电路基础知识: 布尔代数.门级电路的内部晶体管结构.组合逻辑电路分析与设计.触发器.时序逻辑电路分析与设计 2.数字系统的构成: 传感器  AD  数字处理器  D ...

最新文章

  1. 如何到top5%?NLP-情感分析实战训练来教你!
  2. MFC中定义全局变量和全局函数的方法
  3. java after方法_spring AOP的After增强实现方法实例分析
  4. apache安全设置
  5. netty里集成spring注入mysq连接池(二)
  6. 使您的Java 8方法引用生效
  7. [渝粤教育] 西南科技大学 车辆构造 在线考试复习资料
  8. 操作系统之进程管理:20、死锁的检测和解除
  9. 数论 + 公式 - HDU 4335 What is N?
  10. Berkeley DB Java Edition
  11. 【王道操作系统笔记】系统调用
  12. EasyGBS对GB35114的支持
  13. 【换脸软件DFL2.0官方使用手册详解】
  14. 超级好用的高颜值终端工具---Tabby
  15. 深度残差网络+自适应参数化ReLU激活函数(调参记录2)
  16. 【1024个人爆款文章】Android 安卓原生UI实现游戏《俄罗斯方块》,算法太多,把我写崩溃了,附源码
  17. 磨金石教育摄影技能干货分享|乡愁摄影作品欣赏——传统建筑篇
  18. 【java】打印罗马字母和希腊字母(多线程)
  19. 苹果黑屏就断开无线网连接服务器,跪求苹果手机黑屏以后断开无线网的解决方案!...
  20. 杨辉三角(组合数)+排列组合

热门文章

  1. 树莓派搭建transmission下载机
  2. 学生信息管理系统(SSM+JSP)
  3. 如何写一个简单的爬虫程序
  4. proteus三输入与门_proteus元件对照
  5. 网吧网吧无盘服务器配置,网吧无盘服务器配置杂谈
  6. 【回归预测-ELM预测】基于樽海鞘算法结合极限学习机实现风电场功率回归预测附matlab代码
  7. aspx 微型_最初的十亿分钟:正在向世界授课的微型非营利组织背后的数字
  8. 今日头条导航栏动画选中+recyclerview
  9. 省钱兄同城外卖源码O2O同城服务源码校园外卖源码uniapp前端模版
  10. [Python]网络爬虫学习笔记,爬取豆瓣妹子上妹子的照片