tcl脚本(一) - 基本语法

实际脚本用例的讲解请看:tcl脚本用于questasim回归测试

介绍

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

TCL的解释器是用一个C\C++语言的过程库实现的,某种意义上,可以将TCL看做一个C库,每个应用程序都可以根据自己的需要对TCL语言进行扩展。

扩展后的TCL语言将继承TCL核心部分的所有功能,包括核心命令、控制结构、数据类型、对过程的支持等。

学习核心:

  • TCL脚本执行依赖于解释器(逐行执行,没有编译这回事);
  • TCL有效命令行以命令+字符串(结合空间间隔符形成);
  • 明白**置换( $ 、[ ]、 \ )引用( " " 、{ } )**的差别与联系;
  • 明白命令eval、expr、source、exec的差别;
  • 掌握 { * } 配合glob等返回list后的操作。

置换

  • 一个TCL脚本可以包含一个或多个命令。命令之间必须要用换行符或者分号隔开,例如:

    # 以下均合法
    set a 1  #设置a的值为1
    set b 2	 #设置b的值为2
    set a 1;set b 2
    set a 	 ##读取a的值,结果为1
    
  • tcl的每一个命令包含一个或几个单词,第一个单词代表命令名,另外的单词则是这个命令的参数,单词之间必需用空格或Tab隔开

普通置换

TCL解释器在分析命令时,会把所有的命令当做字符串,例如

%set x 10  		#定义变量x,并把x的值赋值为10,这个10也是字符串,而不是我们认为的int等类型
%set y x+100  	#定义变量y,并把y的值赋值为字符串 x+100 ,但注意并非是 110 或者10+100,因为把x当做字符串来看待

变量置换

变量置换有一个 $ 符号标记,如下:

%set x 10 
%set y $x+100   #此时y为字符串 10+100,因为x被置换成了10
#由此我们发现,还不是我们想要的y=110的结果

命令置换

命令置换是由符号 [ ] 括起来的命令及参数,

%set x 10 
%set y [expr $x+100]	#此时y=110

注解:

  • 当TCL解释器。从左到右遇到第一个"[" 时,就会把随后的expr当做一个命令,从而激活expr对应的c/c++过程。
  • 因为中括号[ ]的存在,tcl会把中括号里面的expr $x+100当做一个新的运算来计算,

反斜杠 \ 置换

类似其他语言中的转义字符,在单词符号中插入如换行符、空格、[ 、$等作为特殊符号时,就需要用到 **\ **符号来置换。

%set msg multiple\ space   #添加了一个空格,结果为“multiple space” 

花括号{ }和双引号“”

除了使用反斜杠以外,还可以使用花括号{ }和双引号"",也可以将一些具有命令作用的字符作为特殊字符使用。

双引号""

  • tcl解释器对于双引号""中的各种分隔符将不做处理,但是对换行符以及 $ 和 [ ] 两种置换符会照常处理
%set x 10 
%set y "$x ddd"   #结果为“10 ddd”

花括号{ }

  • 如果变量中有字母、数字或下划线的字符,又要用置换,可以用花括号{ }把变量括起来。
%set a 2
%set a.1 4 		# a.1的值为4
#我们期待  a.1这个变量的值为4,赋值给b,如何操作?
%set b $a.1		# 设置b为2.1,结果不是我们期待的
%set b ${a.1}	# b的值为4,是我们期待的 

%set a {kdfh jk} #设置a为“kdfh jk”
%set a 			#读取a的值,结果为“kdfh jk”

变量

数组

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

%set day(monday) 1  #day是数组名,Monday是数组中的索引值,Monday对应的值为1
%set day(tuesday) 2

相关命令:

  • unset会从解释器中删除变量,后面跟任意多个参数,每个参数是一个变量名(包括数组或数组元素)
% unset a b day(monday)
  • append命令可以将文本追加到一个变量的后面,也就是增加字符串的长度
% set txt hello
% append txt "!world!"  # txt的值为“hello!world!”
  • incr命令是把一个变量的值加上一个整数。要求:变量原来的值和新加的值都必须时整数
%set b 2;incr b 3      #b的结果为5
## 相当于  %set a 2;$set b [expr $a+3]

集合

集合(list)是由一堆元素组成的有序集合。list可以嵌套定义,list中的每个元素可以是任意字符串或list

语法:

  • list ? value value…
  • concat list list …
% list 1 2 {3,4}   # 元素有三个 1 ,2 ,{3,4}
% concat {1 2 3} {4 5 6} # 整合数组 ,{1 2 3 4 5 6}

list相关的命令:

  • **lindex **list index 返回 list 中索引值对应的值,index从0开始计
  • llength list 返回list中的元素个数
  • linsert list index value value… 在list中指定index出插入元素
% lindex {1 2 {3 4}} 2  #返回list的第三个元素,结果为3 4
% llength {1 2 {3 4}}   #返回list中的元素个数
% linsert {1 2 3 4} 1 7 8  #在索引为1处插入 7 8 两个元素,结果为{1 7 8 2 3 4}

控制流

if 命令

  • 语法:if { test1} {body1} elseif {test2} {body 2} …
  • TCL先把test1当做一个表达式求值,如果值非0,则把body1当做一个脚本执行并返回所得值。否则会把Test2当做一个表达式,如果值非0,则把body2当做一个脚本执行。…

注意:

  • "{"必须要在上一行写,不能换行。
  • elseif是连着写的
  • if 和 elseif 与 { 之间要有一个空格,否则解释器会把 if{ 当做一个整体。
if {$x>0} {
...} elseif {$x==1} {
...} elseif {$x<0} {
...} 

while命令

  • 语法:while test body
  • 参数test是一个表达式,body是一个脚本。如果表达式值非0,就运行脚本,直至表达式为0 才停止循环。此时while中断并返回一个空字符串
# 把list a中的数据赋值给了b
set b " "
set i [expr[llength $a] -1]
while {$i>=0} {
lappend b [lindex $a $i]
incr i -1
}

for循环命令

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

foreach循环命令

  • 语法:foreach varName list body
  • 第一个参数varName是变量,第二个是一个list,第三个body是一个循环体。
  • 每次取得链表list中的一个元素,就执行一次循环
set b " "
foreach i $a {
set b [linsert $b 0 $i]
}
# a是一个list 

switch命令

相当于case语句

%switch $x {
b {incr t1}
c{incr t2}
}

其他命令

  • break、continue 命令:中断循环,其中break命令结束整个循环过程,并从循环中跳出,continue只是结束本次循环。
  • source 命令:读一个文件并把文件的内容作为一个脚本进行求值
%source e:/tcl/hello_word.tcl 
  • eval命令:构造和执行TCL脚本命令。可以接受一个或多个参数,然后把所有的参数以空格隔开,组合到一起成为一个脚本,最后对这个脚本求值。
%eval set a 2;set b 4

过程

TCL支持过程的定义和调用,在TCL中,过程可以看做是用TCL脚本实现的命令,效果与TCL固有命令相似。

proc 命令

proc 命令来对过程定义,相当于函数一样的作用

% proc add {x y} {expr $x+$y}
% add 1 2 	# 调用add过程,传递两个参数
# 结果为3

局部变量和全局变量

global在proc中声明变量来自外部,引用外部变量。

% set a 4 
% proc sample {x} {
	global a  #用global声明,这个变量来自外部,即全局变量
	incr a
	return [expr $a+$x]
}
% sample 3 # 值为8
% set a  # 值为5

字符串操作

format命令

语法:format formatstring value value …

按照formatstring提供的格式,把各个value的值组合到formatstring中形成新字符串返回

%set name lisa
%set age 20
%set msg [format "%s is %d years old" $name $age]

scan命令

语法:scan string format varName varName …

可以认为是format命令的逆命令。按照format提供的格式分析string字符串,然后把结果存到变量varName中。

注意:除了空格和TAB键之外,string和format中的字符和百分号 % 必须匹配。

% scan "some 26 34" "some %d %d" a b
%set a	#26
%set b  #34

regexp命令

regexp命令用于判断正则表达式exp是否全部或部分匹配字符串,匹配返回1 ,否则返回0。

字符意义
.匹配任意单个字符
^表示从头到尾进行匹配
$表示从末尾进行匹配
[chars]匹配字符集合chars中给出的任意字符
*对*前门的项进行0次或多次匹配
+对+前门的项进行1次或多次匹配

文件访问

注意:在tcl中,表示文件目录结构时使用的是**“ / ”**,而不是反斜杠“\”

open命令

  • 语法: open name access
  • access方式打开name文件,返回字符串,用于标识打开的文件
  • 当调用别的命令(如:gets,puts,close)对文件进行操作时,都可以使用这个文件标识。
  • stdin.stdout,stderr,分别对应标准输入、标准输出和错误通道
access方式式作用
r默认的打开方式。只读方式打开,且文件必须已经存在。
r+读写方式,且文件已经存在
w只写方式,如果文件存在则情况文件内容,文件不存在就新建一个空文件
w+读写方式,如果文件存在则情况文件内容,文件不存在就新建一个空文件
a只写方式,文件必须存在,并把指针指向文件尾
a+读写方式,如果文件存在,把指针指向文件尾。文件不存在就新建一个空文件

gets命令

  • 语法:gets field varname
  • 读field标识的文件下一行,忽略换行符。
  • 如果命令有varName就把该行赋给它,并返回该行的字符数
  • 如果没有varname,返回文件的下一行作为命令结果
  • 如果到了文件的结尾,就返回空字符串

puts命令

  • 语法:puts nonewline field string
  • puts命令把string写到field中
  • 如果没有 nonewline开关的话,就添加换行符
proc tgrep {pattern filename} {
	set f [open $filename r]  #只读方式打开文件,产生文件标识f
	while {[gets $f line]} {  #获取文件中的每一行,一行一行的拿
		if {[regexp $pattern $line]} {  #判断这一行符不符合正则表达式,也就是我们所期望的
			puts stdout $line #如果符合,就把这一行输出在标准输出端stdout
		}
	}
	close $f
}

flush field

把缓冲区的内容写到field标识的文件中,命令返回值为空。

管理目录的指令包括:

  • pwd 返回当前目录的完整路径
  • cd 使用一个参数,把工作目录改变为参数提供的目录
  • globfile 用来操作文件或者获取文件信息

glob命令

  • 语法:glob switches pattern pattern…
  • glob命令string match命令的匹配规则
# 找到所有以.v和.sv结尾的文件
%glob *.v *.sv  

file命令

语法:file switches pattern pattern…

假如我想删除所有.sv的文件,怎么操作?

file delete *.sv   #不生效,因为file不识别*通配符
#采用一下的方式
file delete {*}[glob *.sv]
#方法二
eval file delete [glob *.sv]

{*} 的存在,是把列表元素作为独立参数提供给指令。比如你glob *.sv返回的是多个文件,文件与文件字符串之间会有空格,tcl会把glob *.sv返回的所有文件名当做一个文件,这样file delete也就无法找到对应的文件。

  • 7
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
回答: shell是一种命令行解释器,用于执行操作系统的命令。tcl是一种脚本语言,常用于自动化任务和快速原型开发。vim是一款文本编辑器,具有强大的功能和灵活的配置选项。 在shell中,可以使用各种命令来执行不同的操作,比如使用ls命令来列出当前目录下的文件和文件夹。在vim中,可以使用不同的命令来编辑和操作文本文件。以下是一些常用的vim命令和基本语法: 1. 打开文件:使用vim命令后跟文件名来打开一个文件,例如:vim file.txt 2. 保存文件:在vim中,可以使用命令:w来保存文件,例如::w 3. 退出vim:使用命令:q来退出vim,例如::q 4. 插入文本:在vim中,按下i键可以进入插入模式,在插入模式下可以输入文本。按下Esc键可以退出插入模式。 5. 删除文本:在vim中,可以使用命令dd来删除一行文本,例如:dd 6. 搜索文本:在vim中,可以使用命令/加上要搜索的文本来搜索文本,例如:/search 7. 替换文本:在vim中,可以使用命令:%s/old/new/g来替换文本,其中old是要替换的文本,new是替换后的文本,g表示全局替换。 以上是一些基本的vim命令和语法,希望对你有帮助。如果你需要更详细的信息,可以参考引用\[1\]和引用\[3\]中提供的内容。 #### 引用[.reference_title] - *1* [vim中执行shell命令小结](https://blog.csdn.net/topgun38/article/details/8013115)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* *3* [vim的常用命令常规操作](https://blog.csdn.net/m0_64097945/article/details/121584418)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小verifier

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值