Tcl基础入门

Tcl基础入门

TCL(Tool Command Language)是一种解释执行的脚本语言(Scripting Language)。它提供了通用的编程能力:支持变量、过程和控制结构;同时TCL还拥有一个功能强大的固有的核心命令集。

1 基础语法

一个TCL脚本可以包含一个或多个命令。命令之间必须用换行符或分号隔开。TCL的每一个命令包含一个或几个单词,第一个单词代表命令名,另外的单词则是这个命令的参数,单词之间必须用空格或TAB键隔开。command <varName> [<value>]

set a 1
set b 2
#或者
set a 1; set b 2

2 置换(substitution)

TCL解释器在分析命令的时候,把所有的命令参数都当作字符串看待

#定义变量x,并把x的值赋值为10
set x 10; #10
#y的值是x+10,不是我们期望的110
set y x+100; #x+100

x被看作字符串“x+100”的一部分,想要实现期望的“110”需要使用TCL语言中提供的置换功能:变量置换、命令置换、反斜杠置换

2.1 变量置换

变量置换用$符号标记,变量置换会将变量的值插入一个单词中。

#y的值是10+100,这里x被置换成它的值10
set y $x+100; #10+100

2.2 命令置换

命令置换使用[]括起来的TCL命令及其参数,命令置换将某一个命令的所有或部分单词被另一个命令的结果所替代。

#y的值是110,达到我们的期望
set y [expr $x+100]; #110

y的值是110,这里当TCL解释器遇到字符[时,它就会把随后的expr作为一个命令名,从而激活与expr对应的C/C++过程,并把expr和变量置换后得到的10+110传递给该命令过程进行处理。
如果在上例中我们去掉[],那么TCL会报错。因为在正常情况下,TCL解释器只把命令行中的第一个单词作为看作命令,其他的单词都作为普通字符串处理,看作是命令的参数。

2.3 反斜杠置换

类似于C语言中反斜杠\的用法,主要用于在单词符号中插入被TCL解释器当作特殊符号(换行符、空格、[、$等)对待的字符。

#msg的值为 multiple space
set msg multiple\ space; #multiple space
#不使用反斜杠会导致解释器将空格当作分隔符,认为set命令多于两个参数,从而报错。

反斜杠置换还有:

在这里插入图片描述

除了使用反斜杠外,TCL提供另外两种方法来使得解释器把分隔符和置换符等特殊字符当作普通字符,而不作特殊处理,这就要使用双引号""和花括号{}
TCL解释器对双引号中的各种分隔符将不作处理,但是对**换行符及$[]**两种置换符会照常处理。

set x 100
set y "$x ddd"; #100 ddd

3 变量

TCL提供两种变量:简单变量和数组

3.1 简单变量

一个TCL的简单变量包含两个部分:名字和值。名字和值都可以是任意字符串。

TCL解释器在分析一个变量置换时,只把$符号往后直到第一个不是字母、数字或下划线的字符之间的单词符号作为要被置换的变量的名字。

set a 2; #2
set a.1 4; #4
set b $a.1; #2.1

这里“.”不是字母、数字或下划线,只会将a置换成a的值。如果变量名中有不是字母、数字或下划线的字符,又要用置换,可以用花括号把变量名括起来。

set b ${a.1}; #4

TCL中的set命令能生成一个变量、也能读取或改变一个变量的值。

#生成变量a
set a {agh hui}; #agh hui
#读取变量a的值
set a; #agh hui

3.2 数组

数组是一些元素的集合。在TCL中,不能单独声明一个数组,数组只能和数组元素一起声明。数组中,数组元素的名字包含两部分:数组名和数组中元素的名字,TCL中数组元素的名字(下标)可以为任何字符串。

#第一个命令生成一个名为day的数组,同时在数组中生成一个名为monday的数组元素,并把值置为1
#第二个命令生成一个名为tuesday的数组元素,并把值置为2。
set day(monday) 1
set day(tuesday) 2

4 相关命令

  • unset:这个命令从解释器中删除变量,它后面可以有任意多个参数,每个参数是一个变量名,可以是简单变量,也可以是数组或数组元素。

    unset a b day(monday)
    
  • append:命令把文本加到一个变量的后面。

    set txt Hello; #Hello
    append txt "! How are you?"; #Hello! How are you?
    
  • incr:命令把一个变量值加上一个整数。incr要求变量原来的值和新加的值都必须是整数

    set b 2; #2
    incr b 3; #5
    

5 表达式

TCL支持常用的数学函数,表达式中数学函数的写法类似于C\C++语言的写法,数学函数的参数可以是任意表达式,多个参数之间用逗号隔开。使用expr命令。

set x 2; #2
expr 2*sin($x<3); #1.6829419
#先将x置换成2,运算2<3成立返回1,sin(1)=0.8474709,2*0.8474709

注意,数学函数并不是命令,只在表达式中出现才有意义,即出现在expr之后才有意义。

6 List

list这个概念在TCL中是用来表示集合的。TCL中list是由一堆元素组成的有序集合,list可以嵌套定义,list每个元素可以是任意字符串,也可以是list。

  • 生成一个list,list的元素就是所有的value

    list 1 2 {3 4}; #1 2 {3 4}
    
  • 整合两个list

    concat {1 2 3} {4 5 6}; #1 2 3 4 5 6
    
  • 返回list的第index个元素:lindex list index

    lindex {1 2 {3 4}} 2; #3 4,返回了下标为2的元素
    
  • 返回list的元素个数:llength list

    llength {1 2 {3 4}}; #3
    
  • 往list插入元素:linsert list index value1 value2 ...

    linsert {1 2 5 6} 2 3 6; #1 2 3 6 5 6
    
  • 把每个value的值作为一个元素附加到变量varname后面: lappend varname value1 value2 ...

    set a 2
    lappend a 1 2 3; #2 1 2 3
    set a; #2 1 2 3
    

7 控制流

  • if命令:if {test1} { body1 }else{ body2 }

    if { $x > 0 }{
      ...} elseif { $x == 1 }{
      ...} else {
      ...}
    

    注意{一定要写在上一行,;同时if{之间应该有一个空格

  • while命令:while {test} {body}

    set b " "
    set i [expr [llength $a] -1]
    while { $i>=0 } {
     lappend b [lindex $a $i]
     incr i -1
    }
    #变量a是一个链表,脚本把a 的值复制到b
    
  • for命令:for init test reinit body,参数init是一个初始化脚本,第二个参数test是一个表达式,用来决定循环什么时候中断,第三个参数reinit是一个重新初始化的脚本,第四个参数body也是脚本,代表循环体。

    set b ""
    for {set i [expr[llength $a] -1]} {$i>=0} {incr i -1} {
      lappend b [lindex $a $i] }
    #变量a是一个链表,脚本把a 的值复制到b
    
  • foreach命令:foreach varName list body,第一个参数varName是一个变量,第二个参数list是一个表(有序集合),第三个参数body是循环体。每次取得链表的一个元素,都会执行循环体一次。

    set b " "
    foreach i $a {
      set b [linsert $b 0 $i]}
    #变量a是一个链表,脚本把a 的值倒序复制到b
    
  • switch命令:switch ?options? string { pattern body ?pattern body ...?},第一个是可选参数options,表示进行匹配的方式。TCL支持三种匹配方式: -exact方式,-glob方式,-regexp方式,缺省情况表示-glob方式-exact方式表示的是精确匹配-glob方式的匹配方式和string match命令的匹配方式相同,-regexp方式是正规表达式的匹配方式。第二个参数string是要被用来作测试的值,第三个参数是括起来的一个或多个元素对。

    switch $x {
      b { incr t1 }
      c { incr t2 }}
    #一旦switch命令找到一个模式匹配就执行相应的脚本,并返回脚本的值,作为switch命令的返回值。
    

8 其它命令

  • 在循环体中,可以用breakcontinue命令中断循环。其中break命令结束整个循环过程,并从循环中跳出,continue只是结束本次循环。

  • source命令读一个文件并把这个文件的内容作为一个脚本进行求值

    source e:/tcl&c/hello.tcl
    
  • eval命令是一个用来构造和执行TCL脚本的命令,其语法为:eval arg ?arg ...? ,它可以接收一个或多个参数,然后把所有的参数以空格隔开组合到一起成为一个脚本,然后对这个脚本进行求值。

    eval set a 2; set b 4
    

9 过程

TCL支持过程的定义和调用,在TCL中,过程可以看作是用TCL脚本实现的命令,效果与TCL的固有命令相似。
TCL中过程是由proc命令产生的:
proc add ix y } {expr $x+$y}
proc命令的第一个参数是你要定义的过程的名字,第二个参数是过程的参数列表,参数之间用空格隔开,第三个参数是一个TCL脚本,代表过程体。proc生成一个新的命令,可以象固有命令一样调用:add 1 2; #3
在定义过程时,你可以利用return命令在任何地方返回你想要的值。return命令迅速中断过程,并把它的参数作为过程的结果。

10 局部变量和全局变量

set a 4;#4
proc sample { x } {
  global a
  incr a
  return [expr $a+$x]}
sample 3; #8
set a;#5

如果我们想在过程内部引用一个全局变量的值,可以使用global命令。如果去掉global a会出错,不能访问到外面的全局变量。过程中定义的变量只能在过程中被访问,称为局部变量。全局变量的作用域不包括所有过程的内部

11 字符串操作

  • format命令类似于sprintf函数,按formatstring提供的格式,把各个value的值组合到formatstring中形成一个新字符串返回。

    set name john
    set age 20
    set msg [format "%s is %d years old" $name $age]
    #john is 20 years old
    
  • scan命令可以认为是format命令的逆,其功能类似于scanf函数。它按format提供的格式分析string字符串,然后把结果存到变量varName中,注意除了空格和TAB键之外,string和format中的字符和’%'必须匹配。

    scan "some 26 34" "some %d %d" a b
    set a
    #26
    set b
    #34
    
  • regexp命令用于判断正规表达式exp是否全部或部分匹配字符串string,匹配返回1,否则0。

在这里插入图片描述

12 文件访问

TCL提供了丰富的文件操作的命令。通过这些命令你可以对文件名进行操作(查找匹配某一模式的文件)、以顺序或随机方式读写文件、检索系统保留的文件信息(如最后访问时间)。

  • open name ?access?:open命令以access方式打开文件name。返回供其他命令(gets,close等)使用的文件标识。

    • r只读方式打开。文件必须已经存在。这是默认方式。r+读写方式打开,文件必须已经存在。
    • w只写方式打开文件,如果文件存在则清空文件内容,否则创建新的空文件。
    • w+读写方式打开文件,如文件存在则清空文件内容,否则创建新的空文件。
    • a只写方式打开文件,文件必须存在,并把指针指向文件尾。
    • a+读写方式打开文件,并把指针指向文件尾。如文件不存在,创建新的空文件
  • TCL有三个特定的文件标识:stdin ,stdoutstderr ,分别对应标准输入、标准输出和错误通道,任何时候你都可以使用这三个文件标识。

  • gets fileId ?varName?:读fileId标识的文件的下一行,忽略换行符。如果命令中有varName就把该行赋给它,并返回该行的字符数(文件尾返回-1),如果没有varName参数,返回文件的下一行作为命令结果(如果到了文件尾,就返回空字符串)。

  • puts ?-nonewline? ?fileId? string :puts命令把string写到fileId中,如果没有nonewline开关的话,添加换行符。fileId默认是stdout。命令返回值为空字符串。

  • flush fileId把缓冲区内容写到fileId标识的文件中,命令返回值为空字符电。

  • 对文件名操作:globfile

    • glob命令的模式采用string match命令的匹配规则:glob ?switches? pattern ?pattern ...?例如:

      glob *.c *.h
      #main.c hash.c hash.h
      
    • file delete *.tmp #不生效不执行通配符展开
      先使用glob命令返回文件列表,在使用参数展开语法{*}把列表元素作为独立参数提供给指令。

      file delete {*}[glob *.tmp]
      #也可以选择使用eval
      eval file delete [glob *.tmp]
      
    • file atime name:访问文件时间

    • file copy source target:复制文件

    • file mkdir dir ?dir...?:在指定目录创建文件夹

    • file owned name:是否有存在此文件

lete *.tmp #不生效不执行通配符展开`
先使用glob命令返回文件列表,在使用参数展开语法{*}把列表元素作为独立参数提供给指令。

```tcl
file delete {*}[glob *.tmp]
#也可以选择使用eval
eval file delete [glob *.tmp]
```
  • file atime name:访问文件时间

  • file copy source target:复制文件

  • file mkdir dir ?dir...?:在指定目录创建文件夹

  • file owned name:是否有存在此文件

  • file executable name:文件是否是可执行文件

  • 6
    点赞
  • 64
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值