首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

Tcl/Tk 快速入门 Tcl 语言-3

Tcl/Tk 快速入门 Tcl 语言-3

变量作用域规则作用域规则描述了过程和变量名以及值在程序的不同层次上的可见性。例如,在脚本的最外层定义的变量是全局变量。缺省情况下,全局变量是不可见的,在过程内部也不可用它们的值。这允许过程的编写者自由地定义变量名并赋值,而不必担心覆盖对于局部作用域上未知的重要变量。要使全局变量在过程内部变得可见,必须将它声明为在过程内,就象在上一屏的示例中,对 PI 使用 global 命令那样。
upvar 命令提供将局部变量与另一个作用域中变量的值相关联的设施。这允许根据名称将变量调用进过程,这对于当过程需要可以修改在另一个作用域的值而不仅仅使用它时,就显得非常方便。这个命令语法是 upvar level $VarName LocalVar,其中 level 是到当前作用域之外的步骤数。“#0”表示全局作用域这一层。
Tcl 中的数据结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#!/usr/bin/tclsh
#
# Demonstrate Data Structures
# using procedural wrappers
  
proc UserAdd { Acct rName eMail phone } {
  global uData

  if {[info exists uData($Acct,rname)]} {
    return 1
    }
  set uData($Acct,rname) $rName
  set uData($Acct,email) $eMail
  set uData($Acct,phone) $phone
  return 0
}
  
puts stdout [UserAdd bpb\
  Brian bilbrey@junk.com 555-1212]
  
puts stdout [UserAdd tom\
  Tom tom@junk.com 555-1212]
  
puts stdout [UserAdd bpb\
  Brian bilbrey@junk.com 555-1212]
   
******
~/tcltk$ ./datas.tcl
0
0
1




除简单的多维数组以外,通常建议用已专门用于过程接口的数组来实现 Tcl 数据结构。从结构的使用者角度来看,虽然这种设计隐藏了具体实现细节,但提供了执行重要的错误检查能力。
左边这个示例中,在将 uData 声明为全局变量后,代码执行检查,以查看帐户是否已经不存在。如果存在,则过程返回(非零)错误消息。这个返回可以用于切换到生成错误文本输出。对于本例,我们简单地提供三个连续输入,其中包括一次重复输入。这会产生如示例底部所示的输出,“1”表示由于一个重复的帐户名称而引起的一个错误返回,这是我们有意这样做的。
其它可能的数据结构包括数组列表、已链接或双重链接的数组或其中的各种排列。因为 Tcl 8.0 所具有的列表重实现提供了不变的访问次数,所以数组列表结构相当有效。
路径和文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
~/tcltk$ tclsh
% file exists hello3.tcl
1
% file executable testit
0
% file pathtype ./hello3.tcl
relative
% set dir1 home
home
% set dir2 brian
brian
% set dir3 tcltk
tcltk
% file join /$dir1 dir2 dir3
/home/dir2/dir3
% file delete testit~
%




文件和路径操作是跨平台环境中具有挑战性的问题。对于主机 OS,Tcl 使用 UNIX 路径名(缺省情况下,用‘/’字符分隔)和本机路径名结构。即使当程序内的数据构造正确时,也很难确保用户输入与系统需求匹配。file join 命令用于将 UNIX 格式转换成本机路径名。其它路径字符串命令包括 file splitdirnamefile extensionnativenamepathtypetail
在它扮演的“工具控制语言”角色中,Tcl 有许许多多种内部文件测试和操作功能。每条命令都以 file 开始,正如 file exists name 中一样。其它测试命令(它们都返回布尔值)包括 executableisdirectoryisfileownedreadablewritable
文件信息和操作(再提醒您一次,所有都是以 file 开始)是通过 atimeattributescopydeletelstatmkdirmtimereadlinkrenamerootnamesizestattype 来完成。请注意,在 Windows 或 Mac 环境中运行一些文件信息命令时,可能会返回未定义的数据,因为例如在那些文件系统中没有表示索引节点和符号(硬)链接数据。
使用 file ... 命令而不使用通过 exec 的本机命令的好处在于,前者会提供一个可移植接口。
整个文档只简单地着重于 Tcl 语言的这一部分。然而,在您“品尝”完左边这个 tclsh 示例中这些命令的味道并对此感到满足之后,然后请继续阅读本教程结尾部分列出的“参考资料”。
Tcl 进程和文件 I/O
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
~/tcltk$ tclsh
% nslookup orbdesigns.com
Server:         192.168.1.3
Address:        192.168.1.3#53
  
Name:   orbdesigns.com
Address: 64.81.69.163
  
% set d [date]
Sun Mar 25 13:51:59 PST 2001
% puts stdout $d
  
% set d [exec date]
Sun Mar 25 13:52:19 PST 2001
% puts stdout $d
Sun Mar 25 13:52:19 PST 2001

******

% if [catch {open foo r} Chan] {
    puts stdout "Sorry, Dave...\n"
}
% gets $Chan
One
% gets $Chan
Two
% eof $Chan
0
% close $Chan
%




exec 命令用于显式地执行外部命令。在 Linux 下,当 Tcl 处于交互方式时,可以直接运行大多数外部命令,如左边示例所示。用 exec 运行时,会将程序的 stdout 输出返回到 Tcl,而不是返回到屏幕,这允许将数据赋值给变量。当程序在后台启动时,立即返回的值是程序的 PID。exec 程序可以充分利用 UNIX 环境中的 I/O 重定向和管道。
其它进程命令有 exit(终止正在运行的 Tcl 脚本)和 pid(返回当前或指定进程的 PID),对于出于各种目的的情况,这非常便利。Tcl 不合并任何本机进程控制命令,但可以将 exec 命令与 PID 数据一起使用来实现许多任务。
文件操纵使用下列命令:openclosegetsputsreadtellseekeofflush。如左边所示,在文件打开命令期间 catch 命令对错误检查是有用的。当在遇到新的一行字符之前需要打印程序输出时,如在用户数据提示符中,使用 flush 来写输出缓冲区。
另外一个功能(在受支持的环境中)是以打开文件的方式打开管道的能力。例如,用 set Channel        [open "|sort foobar" r] 打开管道通道后,第一个 gets 的输出将是“Eight”(文件数据“One”到“Ten”的输出在 10 个单独的行上按字母顺序排列)。
eval 用于动态脚本
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
~/tcltk$ cat input01.txt
1 + 2
4 + 5
7 - 9

~/tcltk$ tclsh
% set InFile [open input01.txt r]
file3
% while {[gets $InFile Op] >= 0} {
    set Operation "expr $Op"
    set Result [eval $Operation]
    puts stdout "$Op = $Result\n"
}
1 + 2 = 3
  
4 + 5 = 9
  
7 - 9 = -2
  
%




在这个示例中,您可以感到 eval 命令的强大功能。在正常情况下,Tcl 解释器以一遍方式(one-pass)操作:它首先对输入的命令行(可能延伸在几个物理行上)进行解析,并执行任何替代。然后开始执行,除非找到不正常或残缺命令。eval 允许第二遍方式(second pass)(或许更精确地讲,是预通过(pre-pass))。因而,可以先动态构造 Tcl 命令,然后进行解析并执行它。
在左边的列表中,输入文件由三行组成,每行都显示了一种算术运算。调用 tclsh 后,文件以只读方式打开并与 $InFile 变量相关联。while 循环每次将一行读入到 $Op 中。然后,通过预先计划将 expr 映射到 $Op 变量来构造整个 Tcl 命令。然后,扩展,求值,从而分配结果。最后,在 stdout 上显示每步操作和结果。
虽然该样本演示了相对琐细的 eval 应用程序,但从概念上讲,可以根据已知语法的输入文件的输入,很容易地将它扩展为动态文件和/或目录处理,或扩展为对文件类型、许可权、访问时间或任何种类的可测试元素的基本操作。
返回列表