文章目录
  1. 1. 配置
  2. 2. 基础
    1. 2.1. 基本规则
    2. 2.2. 变量置换
    3. 2.3. 命令置换
    4. 2.4. 常用命令
  3. 3. 逻辑控制
    1. 3.1. if
    2. 3.2. switch
    3. 3.3. while
    4. 3.4. for和foreach
  4. 4. 过程(函数)
    1. 4.1. 变量作用域
    2. 4.2. 缺省参数
    3. 4.3. 变数量参数
    4. 4.4. 引用
  5. 5. 数据结构
    1. 5.1. 字典
    2. 5.2. 列表
  6. 6. 其他
    1. 6.1. 文件
    2. 6.2. 其它命令
    3. 6.3. 扩展

Fluent是用Scheme编的,Marc是用Fortran编的,Hypermesh是用的TCL,这都是什么鬼东西……

配置

1
apt install tcl

安装完成后,可以得到解释器tclsh,可以直接运行交互式解释器(命令提示符为%),也可以用于运行程序文件。另外,也可以在程序文件开头指明解释器:

1
#!/usr/bin/tclsh

基础

基本规则

TCL 是一种类似shell的命令式语言,各种语句都是command arg1 arg2 ...的形式,其中所有参数都被视为字符串,

  1. TCL会先对字符串进行置换,再进行分析处理。置换包括变量置换、命令置换和转义字符置换。另外,""也可以用于表示含空白字符的字符串,{}则表示原始字符串,其中不会发生任何置换。

  2. 在TCL中,换行和;都表示一句命令结束;#开头的行为注释,因此行内注释需要这样:

1
some command ;# 这是注释

  1. 对于空白比较敏感,例如if{...}是不对的,因为if{会被认为是一个命令,必须用if {...}

变量置换

变量名称较为随便,可包括各种奇怪符号,但是为了变量替换的方便,建议只使用字母、数字和下划线。无需变量声明,使用set赋值,使用$进行变量置换从而取值:

1
2
3
4
5
6
7
8
9
10
11
12
13
%set a 1       ;# a = 1
1
%set b a ;# 由于参数默认为字符串,因而是 b ="a"
a
%set c $a ;# $a 被置换为 a 的值 1
1
%set d $a+2 ;# 尽管 $a 替换了,总体还是字符串,并不会求值
1+2
% set b $a + 2 ;# 空格的存在导致报错
wrong # args: should be "set varName ?newValue?"
%set a.2 4 ;# 奇怪的变量名也可以(尽管不建议)
4
%unset c d ;# 删除变量 c, d,无返回

$变量将$之后直到第一个非字母、数字和下划线字符(以及圆括号)之前的字符视为变量名,因而$a.2会变成1.2;稳妥的方式是使用${a.1}

命令置换

[]内的内容会被认为是一条命令进行运行,其实就类似于匿名函数。两点注意:[]内必须是一或多条完整命令,最后一条的结果被作为输出;[]可以嵌套:

1
2
3
4
5
6
7
8
9
10
%set m [$a+2]               ;# $a+2 并不是完整命令
invalid command name "1+2"
%set m [expr $a+2] ;# expr 为求值命令
3
%set n [expr 7*($a-2)] ;# 基本四则运算
-7
%set n [expr 7*[expr $a-2]] ;# []的嵌套
-7
%set y [expr $a+9; set k 3] ;# 多条语句
3

常用命令

  1. puts aim text :将text输出至aim(可以是文件ID、stdout);可以省略aim参数,则默认输出至stdout

  2. expr formula :返回算式formula的值,算式中数字/变量与运算符之间的空格没有影响。

  3. append var text :把text追加到变量var之后,返回var

  4. incr var_int int :即var_int += int,返回var_intvar_intint都必须可被识别为整数。若省略int,则相当于var_int++

  5. 关系符号:< > <= >= == !=,注意还是必须用到expr才能得到值,值为10

  6. 数学函数:写法类似C,例如

1
2
% expr 2 + sin($a)
2.8414709848078967

逻辑控制

if

1
2
3
4
5
6
7
if {$x > 0} {
....
} elseif {$x == 1} {
....
} else {
....
}

注意空格,注意花括号的左边要留在上一行,不然会被认为语句已结束。

switch

1
2
3
4
5
6
switch options string {
pattern0 - ;# - 表示与后一个相同
pattern1 {body1}
pattern2 {body2}
default {body3}
}

options表示匹配方式,可以为-exact精确匹配、-glob广泛匹配、-regexp正则表达式匹配;可以省略,默认为-glob

while

1
2
3
4
while {$i <= n} {
set k [expr $k + $i]
incr i 1
}

while命令结束后返回空字符串。

for和foreach

1
2
3
for {set i 1} {$i < n} {incr i 1} {
set k [expr $k + $i]
}

for命令结束后返回空字符串。

foreach是针对列表的,类似于python的for i in a

1
2
3
4
set sum 0
foreach i $a {
set sum [expr $sum + $a]
}

也可以实现多重的列表循环:

1
2
3
foreach i {a b c} {i k} {d e f g} {
lappend x $i $j $k
}

最终x的值为a b e b f g c {} {}

过程(函数)

1
2
3
4
5
proc add {x y} {
set m [expr $x + $y]
return $m
}
add 1 2

不用return的话,以最后一条语句的结果作为返回值。

变量作用域

TCL很奇怪,全局变量的作用与不包括过程内部,如果要在过程内引用全局变量,要使用global

1
2
3
4
5
6
7
set a 4
proc sample {x} {
global a
incr a
set m [expr $a + $x]
return $m
}

缺省参数

1
2
3
proc add {x {y 2} {z 3}} {
return [expr $x + $y + $z]
}

变数量参数

1
2
3
proc add { val1 args } {
set sum $val1
foreach i $args { incr sum $i } return $sum }

引用

通过upvar,可以访问到函数参数对应的原变量,类似于C中的引用:

1
2
3
4
5
6
7
8
9
proc temp { arg } {
upvar $arg b
set b [expr $b+2]
}
proc myexp { var } {
set a 4
temp a
return [expr $var + $a]
}

myexp 7输出13

数据结构

字典

一般被称为数组,其实是字典,支持两重的变量置换:

1
2
3
4
5
6
7
8
9
10
% set day(monday) 1
1
% set day(friday) 5
5
% set a monday
monday
% set b $day(monday)
1
% set c $day($a)
1

可以用array命令对字典进行操作,常用包括:

1
2
3
4
# 字典元素个数
array size arrayName
# 返回符合 pattern 的键的列表,若省略 pattern 则返回所有键
array names arrayName pattern

列表

可包含任意的字符串或子列表,可以直接用花括号声明或者用list命令,注意用空格而不是逗号分隔:

1
2
3
4
5
% set a {}
% set b {c g 6 .}
c g 6 .
% set c [list 1 3 {4 q} $b]
1 3 {4 q} {c g 6 .}

访问数组元素需要使用lindex list indexNumber命令,注意第一变量需要是$x而不是x,下标从0开始:

1
2
% puts [lindex [lindex $c 3] 2]
6

其它命令:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
% llength {1 2 {3 4}}    ;# 元素个数
3
% # linsert list indexNumber value
% # 把 value 插入到 index 号元素之前,返回新列表
% linsert {2 3 6} 1 {7 8}
{2 {7 8} 3 6}
% linsert b 1 mm
b mm
% linsert $b 1 mm ;# 第一参数是 list 而不是变量名
c mm g 6 .
% # lappend listName value
% # 把 value 追加到列表最后(若该名字的列表不存在则创建它),返回新列表
% lappend $b 0 9
0 9
% lappend $b 0 9 ;# 第一参数是变量名而不是list
c g 6 . 0 9
% lappend $b {0 9}
c g 6 . 0 9 {0 9}
% # lrange list first last
% # 列表切片,包含两端;last 可以是 end
% lrange {1 7 8 2 4 5 6} 2 5
8 2 4 5
% lrange {1 7 8 2 4 5 6} 3 end
2 4 5 6

其他

文件

  1. open fileFullName access:以access方式打开file,返回文件标识符。打开方式包括:
参数 打开方式 对文件的要求
r 只读 文件已存在
r+ 读写 文件已存在
w 只写 已存在则清空文件,否则创建文件
w+ 读写 已存在则清空文件,否则创建文件
a 追加 文件已存在
a+ 只读 文件已存在,否则创建文件
  1. close fileID:关闭file,返回空字符串。

  2. gets fileID varName:读取file的下一行,赋给var,返回字符数。

  3. read -nonewline fileID:读取并返回file所剩的全部内容。

  4. puts fileID string:把字符串写入file,结尾添加换行符(采用-nonewline参数禁止)。fileID也可以是stdin, stdout, stderr,省略则默认为stdout

  5. flush fileID:把缓冲区的数据写入文件中,一般在close时会自动flush

  6. pwdcd:类似bash命令,分别是获取当前路径与切换路径。

其它命令

  1. eval:把所有参数以空格隔开组成一个脚本,如

1
2
% eval set a 2 ; set b 4
4

  1. source:读入文件并将其作为脚本求值,注意使用/而不是\

1
2
% source e:/tcl/hello.tcl
Hello

扩展

TCL支持的数据类型较少,也不能面向对象编程,incr TCL(捏他C++)解决了这一问题:

1
apt install itcl
文章目录
  1. 1. 配置
  2. 2. 基础
    1. 2.1. 基本规则
    2. 2.2. 变量置换
    3. 2.3. 命令置换
    4. 2.4. 常用命令
  3. 3. 逻辑控制
    1. 3.1. if
    2. 3.2. switch
    3. 3.3. while
    4. 3.4. for和foreach
  4. 4. 过程(函数)
    1. 4.1. 变量作用域
    2. 4.2. 缺省参数
    3. 4.3. 变数量参数
    4. 4.4. 引用
  5. 5. 数据结构
    1. 5.1. 字典
    2. 5.2. 列表
  6. 6. 其他
    1. 6.1. 文件
    2. 6.2. 其它命令
    3. 6.3. 扩展