Tcl 编程/函数
命令基本上分为 C 定义的命令、过程和别名(以及从 Tcl 8.5 开始的组合)。您可以使用
rename oldname newname
要删除命令(使其不再可访问),请使用空字符串作为新名称
rename oldname {}
内省:使用
info commands
这些命令在 C 中实现,并注册为在 Tcl 解释器中可用。它们可以来自 Tcl 核心,也可以来自已加载的共享库(DLL)- 例如 Tk。
要获取内置命令的列表,请从 info commands 的结果中减去 info procs 的结果
set builtins {} set procs [info procs] foreach cmd [info commands] { if {[lsearch -exact $procs $cmd] == -1} {lappend builtins $cmd} }
以下 C 定义的命令在新的 tclsh 中可用。有关详细文档,请参阅相应的联机帮助页,例如,在 http://www.tcl.tk/man/tcl8.5/TclCmd/ - 我将只对每个命令进行简要描述
- after
- 用于定时事件的命令组
- after msec ?script?
- 等待或在一段时间后执行脚本
- append varName arg..
- 将参数追加到字符串变量
- array
- 用于数组的命令组
- binary
- 用于二进制扫描和格式化的命令组
- break
- 终止当前循环
- case
- 已弃用,使用 switch
- catch script ?varName?
- 捕获 script 中的可能的错误
- cd path
- 更改工作目录
- clock
- 处理日期和时间的命令组
- close handle
- 关闭通道(文件、套接字等)
- concat list..
- 将参数合并成一个空格分隔的列表
- continue
- 开始当前循环的下一个迭代
- encoding
- 处理字符集编码的命令组
- eof handle
- 如果通道位于文件末尾,则为 1,否则为 0
- error message ?info? ?code?
- 使用给定消息引发错误
- eval arg..
- 将参数作为脚本进行评估
- exec file arg..
- 执行一个独立的进程
- exit ?int?
- 终止此进程,返回状态 0..127
- expr arg..
- 算术和逻辑引擎,使用类似于 C 的语法和函数(变量引用使用 $name)。此外,从 Tcl 8.4 开始,有 eq 和 ne 运算符用于字符串相等或不相等;从 8.5 开始,还有 in 和 ni 运算符用于列表包含或不包含
expr {"foo" in {foo bar grill}} == 1
expr 的参数在大多数情况下应该是 {花括号括起来的}。这可以防止 Tcl 解析器预先替换变量,而 expr 本身必须从字符串中解析值。在花括号括起来的表达式中,expr 可以自行解析变量引用,并在可能的情况下直接获取其数值。通常更快。唯一的例外是,当您想要从变量中替换运算符时,不应使用花括号
foreach op {+ - * /} {puts [expr 1 $op 2]}
- fblocked handle
- 如果上次输入操作用尽了所有可用输入,则返回 1,否则返回 0
- fconfigure handle -option value...
- 配置通道,例如其编码或换行符转换
- fcopy handle1 handle2
- 将数据从 handle1 复制到 handle2
- file
- 处理文件的命令组
- fileevent
- 处理通道(可读、可写)事件(但不是文件)的命令组
- flush handle
- 确保通道的缓冲区已写入。在 puts -nonewline 之后很有用
- for initbody condition stepbody body
- 循环,与 C 的 for 有些类似
- foreach varlist list ?varlist list...? body
- 遍历一个或多个列表。varlist 可以是单个或多个 varName。例如
% foreach {x y} {1 0 1 2 0 2 0 0} {puts "x:$x, y:$y"} x:1, y:0 x:1, y:2 x:0, y:2 x:0, y:0
- format fstring arg..
- 将参数 %-格式化为 fstring,类似于 C 的 sprintf()
- gets handle ?varName?
- 从 handle 读取一行。如果给出变量,则将行分配给它并返回读取的字符数;否则返回行。保证防范缓冲区溢出
- glob ?-options? pattern..
- 匹配 glob 模式(可以包含 * 和 ? 通配符)的文件列表
- global varName..
- 声明给定的变量为全局变量
- history
- 列出最近的交互式命令
- if condition ?then? body1 ?elseif condition body2...? ??else? bodyN?
- 条件语句
- incr varName ?amount?
- 将整数变量增加给定的数量(默认为 1)。使用负数来减少
- info
- 用于内省的命令组
- interp
- 用于解释器的命令组
- join list ?separator?
- 将列表转换为字符串,在元素之间使用分隔符(默认为 " ")
- lappend varName arg..
- 将参数追加到列表变量。也可以用于确保变量存在
lappend x ;# corresponds to: if {![info exists x]} {set x ""}
- lindex list int..
- 通过整数索引(es)检索列表中的元素
- linsert list int arg..
- 在列表的 int 位置插入参数
- list ?arg..?
- 从参数创建列表
- llength list
- 列表的长度
- load filename ?name?
- 加载共享库(DLL)
- lrange list from to
- 返回整数索引 from-to 处的子列表
- lreplace list from to arg..
- 用参数替换列表中的子列表
- lsearch ?-options? list element
- 在列表中搜索元素,返回其整数索引,如果未找到,则返回 -1。可用于从列表中选择元素子集(使用 -all 选项)
- lset varName int.. value
- 将命名列表变量中的现有元素设置为给定值,该元素由整数(es)索引
- lsort ?-options? list
- 对列表进行排序
- namespace
- 处理命名空间的命令组
- open name ?mode ?permissions??
- 打开文件或管道,返回句柄
- package
- 处理包的命令组
- pid ?handle?
- 返回当前进程的 ID。也可以返回给定管道通道的管道的 pid 列表
- proc name arglist body
- 定义过程
- puts ?-nonewline? ?channel? string
- 将一行输出到给定的通道(默认情况下为 stdout)。要防止从已关闭的管道(如 more 或 head)中出现错误,请使用
proc puts! str {if [catch {puts $str}] exit}
- pwd
- 返回当前工作目录
- read handle ?int?
- 从 handle 读取 int 个字节(如果没有给出 int,则读取所有字节)
- regexp ?-options? re string ?varName...?
- 在字符串中匹配 re 的正则表达式,可能将带括号的子匹配分配给给定的变量
- regsub ?-options? re value substring ?varName?
- 用子字符串替换 value 中正则表达式 re 的出现次数。如果给出 varName,则将新值分配给它,并返回替换次数;否则返回新值
- rename cmdName1 cmdName2
- 将命令从 cmdName1 重命名为 cmdName2,如果 cmdName2 为 {},则删除 cmdName1
- return ?value?
- 退出当前过程或已源代码化的脚本
- scan string format ?varName...?
- 根据字符串中的 %-格式提取值到给定的变量。类似于 C 的 sscanf()
- seek channelId offset ?origin?
- 将文件中的指针移动到给定位置
- set varName ?value?
- 如果给出,则将变量设置为值,并返回变量的值
- socket ?-myaddr addr? ?-myport myport? ?-async? host port
- 打开 TCP 连接的客户端作为通道
- socket -server command ?-myaddr addr? port
- 打开 TCP 连接的服务器端,为客户端请求注册一个处理程序回调命令
- source filename
- 评估给定文件的内容
- split list ?charset?
- 将字符串拆分为列表,使用 charset 字符串中的任何字符作为分隔符(默认为 " ")
- string
- 处理字符串的命令组
- subst ?-options? string
- 在字符串中执行命令、变量或反斜杠替换
- switch ?-options? ?--? value alternatives
- 如果值匹配,则执行一个备选方案
- tell handle
- 返回文件内部的字节位置
- time body ?int?
- 运行 body int 次(默认 1),返回每次迭代使用了多少微秒
- trace
- 用于将操作绑定到变量或命令的命令组
- unset varName..
- 删除给定的变量
- update ?idletasks?
- 服务事件
- uplevel ?level? body
- 在调用堆栈中向上评估 body
- upvar ?level? varName localVarName...
- 将给定的变量绑定到调用堆栈中的给定局部变量。用于按引用调用,例如用于数组
- variable varName ?value ?varName value...??
- 声明变量在命名空间中是非局部的
- vwait varName
- 挂起执行,直到给定变量发生变化。如果事件循环尚未激活,则启动它
- while condition body
- 只要条件不为 0,就执行 body
Tcl 中的过程对应于其他语言中的过程、子程序或函数。它们始终返回一个结果(即使是空字符串 ""),因此称它们为函数可能最合适。但出于历史原因,用于创建函数的 Tcl 命令称为 **proc**,因此人们通常称它们为过程。
proc name argumentlist body
示例
proc sum {a b} {return [expr {$a+$b}]}
return 是多余的,因为 proc 在到达其末尾并返回其最后一个结果时会自动返回。
proc sum {a b} {expr {$a+$b}}
以下变体更加灵活,因为它接受任意数量的参数(特殊参数名 args 将所有剩余参数收集到一个列表中,该列表是参数 args 的值)。
proc sum args { set res 0 foreach arg $args {set res [expr {$res + $arg}]} return $res }
一个优雅但效率较低的替代方法是通过 join 使用加号连接 args 来构建字符串,并将该字符串提供给 expr。
proc sum args {expr [join $args +]}
如果 proc 定义中的参数是一个包含两个元素的列表,则如果在调用中未给出第二个元素,则将其作为默认值(在本例中为 "Sir")。
proc greet {time {person Sir}} {return "good $time, $person"}
% greet morning John good morning, John % greet evening good evening, Sir
**内省:** 使用以下命令获取所有已定义过程的名称。
info procs
还有一些 **info** 子命令可以获取过程的参数列表、可能的默认参数和主体。以下示例将它们结合起来,根据名称重新创建过程的文本形式(corp 是 proc 的反向)。
proc corp name { set argl {} foreach arg [info args $name] { if [info default $name $arg def] {lappend arg $def} lappend argl $arg } list proc $name $argl [info body $name] }
使用 **rename**,您可以重载任何命令,包括 C 编码的命令。首先将原始命令重命名为其他名称,然后使用相同的签名重新实现它,最终调用原始命令。例如,以下是一个重载的 proc,它报告是否多次使用相同的名称定义了过程。
rename proc _proc _proc proc {name argl body} { if {[info procs $name] eq $name} { puts "proc $name redefined in [info script]" } _proc $name $argl $body }
**命名参数:** 命令的参数主要通过位置传递。但是,很容易添加 Python 或 Ada 中已知的行为,即参数可以在函数调用中命名,这可以更好地记录代码,并允许以任意顺序传递参数。
这个想法(正如在 Welch 的书中发现的那样)是使用一个数组(这里称为 "" - "匿名数组"),该数组以参数名为键。最初,您可以设置一些默认值,并可能使用 proc 的参数覆盖它们(该参数必须成对,即包含偶数个元素)。
proc named {args defaults} { upvar 1 "" "" array set "" $defaults foreach {key value} $args { if {![info exists ($key)]} { set names [lsort [array names ""]] error "bad option '$key', should be one of: $names" } set ($key) $value } }
用法示例
proc replace {s args} { named $args {-from 0 -to end -with ""} string replace $s $(-from) $(-to) $(-with) }
测试
% replace suchenwirth -from 4 -to 6 -with xx suchxxirth % replace suchenwirth -from 4 -to 6 -witha xx bad option '-witha', should be one of: -from -to -with
通常,命令的参数按值传递(作为常量,或在变量名前面加上 $)。这可以安全地防止副作用,因为命令只会获得值的副本,而无法更改变量。
但是,有时就是需要这样。想象一下,您想要一个自定义命令将变量设置为零。在这种情况下,在调用时指定变量的名称(不带 $),并在 proc 中使用 **upvar** 将名称(在范围 "1 up" 中,即调用者的范围)链接到本地变量。我通常在作为变量名的参数前面加上一个 _(例如 _var),并将 upvar 链接到没有 _ 的相同名称(例如 var)。
% proc zero _var {upvar 1 $_var var; set var 0}
% set try 42 42 % zero try 0 % set try 0
如果您经常使用按引用调用,您可以使用特殊模式(例如 &arg)来指示此类参数,并使用以下代码生成必要的 **upvar**。
proc use_refs { {char &}} { foreach v [uplevel 1 {info locals}] { if [string match $char* $v] { uplevel 1 "upvar 1 \${$v} [string range $v 1 end]" } } }
就是这样。最好先在 proc 内部调用此命令,并对以特定字符开头的所有参数进行 upvar 操作,默认字符为 "&" - 它运行类似于以下代码的代码
upvar 1 ${&foo} foo
在调用者的范围内。测试
proc test_refs {a &b} { use_refs puts a=$a,b=$b set b new_value } % set bar 42 42 % test_refs foo bar a=foo,b=42
因此,a(按值传递)和 b(按引用传递)的值是可读的;并且在调用者中更改 b 的副作用也发生了。
% set bar new_value
在过程内部,变量默认情况下是本地的。它们只存在于 proc 中,并在 return 时被清除。但是,您可以将本地变量绑定到调用堆栈中更高的变量(例如,在调用者中),直到最顶层的全局范围。
proc demo arg { global g set g 0 ;# will effect a lasting change in g set local 1 ;# will disappear soon set ::anotherGlobal 2 ;# another way to address a global variable upvar 1 $arg myArg ;# make myArg point at a variable 1-up set myArg 3 ;# changes that variable in the calling scope }
还可以将命令定义为一个或多个单词序列的别名,这些单词将在执行之前替换它。(有趣的是 {} 参数是源和目标解释器的名称,它们通常是当前解释器,由空字符串 {} 或 "" 命名)。示例
interp alias {} strlen {} string length interp alias {} cp {} file copy -force
内省:使用以下命令获取所有已定义别名的名称。
interp aliases
Tcl 是一种解释型(加上即时字节编译)语言,因此解释器当然是一种核心类型的对象。每次运行 Tcl 时,至少会运行一个解释器,它接收脚本并对其进行评估。
还可以创建额外的 "从属" 解释器来封装数据和进程,这些解释器又可以有它们自己的 "子从属" 解释器,依此类推,最终形成一个树形层次结构。示例
% interp create helper helper % helper eval {expr 7*6} 42 % interp delete helper % helper eval {expr 1+2} invalid command name "helper"
通过删除解释器,所有全局变量(以及命名空间变量)也会被释放,因此,如果需要,您可以使用它来进行模块化和封装。
特别是,**安全解释器** 故意限制了功能(例如,访问文件系统或 Web),因此来自 Web 的可能恶意代码无法造成重大破坏。
内省:以下命令列出当前解释器的子解释器("从属")。
% interp slaves
集成(从 Tcl 8.5 开始),是指根据标准模式由子命令组成的命令。例如,Tcl 的内置 **chan** 和 **clock** 命令。子命令的调度以及对不存在子命令的提示性错误消息都是内置的。子命令位于名为 "-map" 的 dict 结构中,包含交替的名称和操作。非常简单的示例
namespace ensemble create -command foo -map \ {bar {puts Hello} grill {puts World}}
创建了一个名为 foo 的命令,它可以像下面这样调用。
% foo bar Hello % foo grill World % foo help unknown or ambiguous subcommand "help": must be foo, or bar
显然,集成也是实现面向对象编程的一个很好的基础,其中命令是对象的名称,映射包含其方法。
**内省:** 使用以下命令序列化集成的映射。
namespace ensemble configure $name -map
命名空间是用于存放过程、非局部变量和其他命名空间的容器。它们形成一个树形结构,根位于名为 "::" 的全局命名空间。它们的名称也使用 :: 作为分隔符,因此 ::foo::bar 是 ::foo 的子节点,::foo 是 :: 的子节点(类似于 Unix 上的路径名,其中 / 既是分隔符又是根)。
简而言之,命名空间是一个单独的区域,或者说是 范围,过程和变量在该范围内可见,并且对该范围私有。
要创建命名空间,只需在其中 eval 某些脚本(可以为空)。
namespace eval ::foo {}
现在您可以使用它来定义过程或变量。
proc ::foo::test {} {puts Hello!} set ::foo::var 42
要删除命名空间(并清理其所有变量、过程和子命名空间),可以使用以下命令。
namespace delete ::foo
内省
namespace children :: info var namespace::* info commands namespace::*
以下代码给出了 Tcl 命名空间(其中 ::,即全局命名空间,特别有趣 - 所有(孙)子节点也被添加)的变量和子节点所占用的字节大小的近似值。如果您多次调用此 proc,则可以观察数据是否正在累积。
proc namespace'size ns { set sum [expr wide(0)] foreach var [info vars ${ns}::*] { if {[info exists $var]} { upvar #0 $var v if {[array exists v]} { incr sum [string bytelength [array get v]] } else { incr sum [string bytelength $v] } } } foreach child [namespace children $ns] { incr sum [namespace'size $child] } set sum }
用法示例
% puts [namespace'size ::] 179914
Tcl 用户传统上对线程(轻量级并发子进程)持怀疑态度 - 事件循环模型已被证明非常强大,并且更容易调试。最初来自 Tk,事件循环已经迁移到 Tcl,并用于
- 文件事件(比实际文件更关注通道)
- 计时事件
- UI 事件(用户进行的鼠标或键盘操作)
但是,在 Tcl 构建中启用线程的趋势正在增长。底层模型是每个线程都在它自己的解释器中运行,因此它基本上与外部世界隔离。线程之间的通信必须使用显式方法进行。
包是 Tcl 推荐的模块化软件,尤其是支持库。用户最常使用的命令是
package require name ?version?
您可以使用纯 Tcl 或作为扩展的包装器来编写包,扩展包括一个或多个已编译的共享库(以及可选的一个或多个 Tcl 脚本)。流行的扩展包括
- BWidget(将有用的部件添加到 Tk - 更多内容见下文)
- Expect(支持通过网络进行远程执行)
- Img(将对 Tk 添加对其他图像文件格式的支持)
- snack(声音输入/输出)
- Snit(OO 扩展,支持 Tk 中的 "超级部件")
- sqlite(一个微小但功能强大的 SQL 数据库)
- tcllib(一个纯 Tcl 包的集合 - 更多内容见下文)
- TclOO(从 8.5 开始的规范面向对象扩展)
- tcltcc(一个内置的 C 编译器 - 更多内容见下文)
- TclX(系统相关扩展的集合,例如信号处理)
- tdom(XML 解析器,SAX 或 DOM,带有 XPath 查询支持)
- Tk(跨平台 GUI 工具包,更多内容见下文)
- tkcon(一个扩展了的功能丰富的控制台)
- XOTcl(高级动态 OO 扩展)
以下脚本创建了一个简单的但有教育意义的包 futil,它在同名的命名空间中实现了两个用于读取和写入完整文本文件的 proc,以及一个小的内省辅助函数 futil::?。注册包(package provide)的命令仅在一切顺利后才执行 - 这样,有错误的源代码,在包要求期间引发错误,将不会被注册。(其他错误你必须自己发现并修复...)
常见的 Tcl 分发实践有一个很好的习惯,即进行深入的测试,通常是在一个单独的测试目录中。另一方面,在同一个文件中将自测试包含在代码中使编辑更容易,因此在 package provide 之后,只会在将此文件作为顶层脚本源代码时执行的部分,它会练习在 futil 中定义的命令。是否应该将读取的字符串与写入的字符串相等是可争议的 - 当前实现如果字符串不以 \n 结尾,就会将 \n 附加到字符串中,因为有些工具会抱怨或行为异常,如果它们没有看到最后的换行符。
如果测试也没有遇到任何错误,即使是包索引的必要构造也会被触发 - 假设目录中只包含一个包。否则,你最好删除这些行,并自己处理索引创建。
使用此包的脚本只需要包含这两行
lappend ::auto_path <directory of this file> package require futil
如果你安装(复制)包含源代码和 pkgIndex.tcl 的目录到 ${tcl_install_directory}/lib 下,你甚至可以省略第一行。
namespace eval futil { set version 0.1 }
但现在回到组成包的单个脚本(将其保存为 futil.tcl 会更有意义)。我们在 futil 命名空间中提供了一个 read 和一个 write 函数,外加一个小的内省函数 ?,它返回可用函数的名称
proc futil::read {filename} { set fp [open $filename] set string [::read $fp] ;# prevent name conflict with itself close $fp return $string } proc futil::write {filename string} { set fp [open $filename w] if {[string index $string end]!="\n"} {append string \n} puts -nonewline $fp $string close $fp } proc futil::? {} {lsort [info procs ::futil::*]} # If execution comes this far, we have succeeded ;-) package provide futil $futil::version
#--------------------------- Self-test code if {[info ex argv0] && [file tail [info script]] == [file tail $argv0]} { puts "package futil contains [futil::?]" set teststring { This is a teststring in several lines...} puts teststring:'$teststring' futil::write test.tmp $teststring set string2 [futil::read test.tmp] puts string2:'$string2' puts "strings are [expr {$teststring==$string2? {}:{not}}] equal" file delete test.tmp ;# don't leave traces of testing
# Simple index generator, if the directory contains only this package pkg_mkIndex -verbose [file dirn [info scr]] [file tail [info scr]] }
Tcllib
[edit | edit source]Tcllib 是一个纯 Tcl 包的集合。它可以从 sourceForge 获取,但也是 ActiveTcl 的一部分。以下包含的包列表可能不完整,因为 Tcllib 正在不断增长...
- aes - 高级加密标准。
- asn - asn.1 BER 编码器/解码器
- http/autoproxy - 用于自动使用 HTTP 代理服务器的代码
- base64 - 字符串和文件的 Base64 编码和解码。
- bee - BitTorrent 序列化编码器/解码器。
- bibtex - Neil Madden 的 bibtex 文件解析器。尚未完全完成,因此未设置为安装。
- calendar - 日历操作(参见 tcllib 日历模块)。
- cmdline - 各种形式的命令行和选项处理。
- comm - 基于套接字的进程间通信。模拟 Tk 的 send 命令的形式。
- control - 用于 tcl 流程结构的程序,如 assert、do/until、do/while、no-op
- counter - 用于计数器和直方图的程序
- crc - 计算字符串和文件的各种 CRC 校验和。
- csv - 操作逗号分隔值数据
- des - 数据加密标准。 ::DES::des (尚未安装)
- dns - 与域名系统交互。 dns::address、dns::cleanup、dns::cname、dns::configure、dns::name、dns::reset、dns::resolve、dns::status、dns::wait,
- doctools - 用于以简单但强大的格式编写手册页/文档的系统。
- exif - exif::analyze exif::fieldnames
- fileutil - 用于操作文件的实用程序,模拟各种 unix 命令行应用程序(cat、find、file(type)、touch、...)。
- ftp - FTP(文件传输协议)的客户端实现。迫切需要重写。
- ftpd - FTP 的服务器端实现
- grammar_fa - 对有限自动机进行操作。
- html - 从 Tcl 脚本生成 HTML。 html::author、html::author、html::bodyTag、html::cell、html::checkbox、html::checkSet、html::checkValue、html::closeTag、html::default、html::description、html::description、html::end、html::eval、html::extractParam、html::font、html::for、html::foreach、html::formValue、html::getFormInfo、html::getTitle、html::h、html::h1、html::h2、html::h3、html::h4、html::h5、html::h6、html::hdrRow、html::head、html::head、html::headTag、html::if、html::init、html::init、html::keywords、html::keywords、html::mailto、html::meta、html::meta、html::minorList、html::minorMenu、html::openTag、html::paramRow、html::passwordInput、html::passwordInputRow、html::radioSet、html::radioValue、html::refresh、html::refresh、html::row、html::select、html::selectPlain、html::set、html::submit、html::tableFromArray、html::tableFromList、html::tagParam、html::textarea、html::textInput、html::textInputRow、html::title、html::title、html::urlParent、html::varEmpty、html::while,
- htmldoc - 这不是一个真正的模块,而是 tcllib 1.3 安装 tcllib 文档的 HTML 格式的地方。
- htmlparse - 用于允许对包含 HTML 的字符串进行有限操作的程序。 ::htmlparse::parse、 ::htmlparse::debugCallback、 ::htmlparse::mapEscapes、 ::htmlparse::2tree、 ::htmlparse::removeVisualFluff、 ::htmlparse::removeFormDefs,
- ident - RFC 1413 ident 客户端协议实现
- imap4 - 当前用于与 IMAP 服务器交互的未记录代码
- inifile - 用于操作初始化文件的代码。 ::ini::open、 ::ini::close、 ::ini::commit、 ::ini::sections、 ::ini::keys、 ::ini::value
- dns/ip - IP 地址的操作。 ::ip::version、 ::ip::is、 ::ip::normalize、 ::ip::equal、 ::ip::prefix
- irc - 互联网中继聊天程序。 irc::config、irc::connection,
- javascript - 生成 Javascript 以包含在 HTML 页面中。 javascript::BeginJS、javascript::EndJS、javascript::MakeMultiSel、javascript::MakeClickProc、javascript::makeSelectorWidget、javascript::makeSubmitButton、javascript::makeProtectedSubmitButton、javascript::makeMasterButton、javascript::makeParentCheckbox、javascript::makeChildCheckbox
- jpeg - 编辑注释块,获取 JPG 格式图像的尺寸和信息,读取图像的 exif 数据
- ldap - LDAP(轻量级目录访问协议)的客户端实现。
- log - 用于将日志条目添加到文件的通用程序。 ::log::levels、 ::log::logMsg、 ::log::lv2longform、 ::log::lv2color,::log::lv2priority,
- logger - ::logger::walk、 ::logger::services、 ::logger::enable、 ::logger::disable (日志模块的一部分)
- math - 通用数学程序。 ::math::calculus、 ::math::combinatorics、 ::math::cov、 ::math::fibonacci、 ::math::integrate、 ::math::interpolate、 ::math::max、 ::math::mean、 ::math::min、 ::math::optimize、 ::math::product、 ::math::random、 ::math::sigma、 ::math::statistics、 ::math::stats、 ::math::sum
- md4 - ::md4::md4、 ::md4::hmac、 ::md4::MD4Init、 ::md4::MD4Update、 ::md4::MD4Final
- md5 - [填写此模块的描述] ::md5::md5、 ::md5::hmac、 ::md5::test、 ::md5::time、 ::md5::<<<
- md5crypt - ::md5crypt::md5crypt、 ::md5crypt::aprcrypt
- mime - ::mime::initialize、 ::mime::parsepart、 ::mime::finalize、 ::smtp::sendmessage
- multiplexer - [填写外部接口]
- ncgi - 用于 CGI 应用程序的程序。 ::ncgi::reset、 ::ncgi::urlStub、 ::ncgi::urlStub
- nntp - 用于与 Usenet 新闻服务器交互的例程。 ::nntp::nntp、 ::nntp::NntpProc、 ::nntp::NntpProc、 ::nntp::okprint、 ::nntp::message,
- ntp - 网络时间协议程序 ::ntp::time
- png - 编辑注释块,获取可移植网络图形格式的图像尺寸和信息。
- pop3 - 用于从 pop3 服务器读取邮件的邮局协议函数。 ::pop3::open、 ::pop3::close、 ::pop3::status,
- pop3d - 邮局协议服务器。 pop3d::new
- profiler - ::profiler::tZero、 ::profiler::tMark、 ::profiler::stats、 ::profiler::Handler、 ::profiler::profProc、 ::profiler::init
- rc4 - 流加密。 ::rc4::rc4
- report - 以各种报告样式格式化文本。 ::report::report , ::report::defstyle、 ::report::rmstyle,
- sha1 - ::sha1::sha1、 ::sha1::hmac
- smtpd - ::smtpd::start、 ::smtpd::stop、 ::smtpd::configure、 ::smtpd::cget
- snit - Snit's Not Incr Tcl - OO 包。基于委托。 ::snit::type、 ::snit::widget、 ::snit::widgetadaptor
- soundex::knuth - 基于字母理论发音的字符串匹配
- stooop - OO 包。 stooop::class、stooop::virtual、stooop::new、stooop::delete、stooop::classof
- struct1 - struct 的版本 1(见下文),为向后兼容性提供。
- struct::list、 ::struct::graph、 ::struct::matrix、 ::struct::queue、 ::struct::stack、 ::struct::Tree、 ::struct::record、 ::struct::skiplist、 ::struct::prioqueue,新建: ::struct::sets
- tar - 解压缩、列出和统计 tar 包中的文件,以及创建新的 tar 包
- textutil - 用于处理大量文本的实用程序。 textutil::expand - expand 宏处理器的核心。
- tie - Tcl 数组的持久性。
- treeql - 树查询语言,灵感来自 COST。
- uri - 处理 uri/url(拆分、合并、...)
- uuid - 创建唯一标识符。
TclOO
[edit | edit source]TclOO 是一个可加载的包,用于提供面向对象编程的基础,旨在使 Itcl、Snit 或 XOTcl 等特定 OO 风格能够构建在它之上。但它本身也是一个可用的 OO 系统,提供类、多重继承、mixin 和过滤器。以下是一些示例代码,让你了解一下
#!/usr/bin/env tclsh85 package require TclOO namespace import oo::* class create Account { constructor { {ownerName undisclosed}} { my variable total overdrawLimit owner set total 0 set overdrawLimit 10 set owner $ownerName } method deposit amount { my variable total set total [expr {$total + $amount}] } method withdraw amount { my variable {*}[info object vars [self]] ;# "auto-import" all variables if {($amount - $total) > $overdrawLimit} { error "Can't overdraw - total: $total, limit: $overdrawLimit" } set total [expr {$total - $amount}] } method transfer {amount targetAccount} { my variable total my withdraw $amount $targetAccount deposit $amount set total } destructor { my variable total if {$total} {puts "remaining $total will be given to charity"} } }
tcltcc
[edit | edit source]Tcltcc 是一个可加载的包,它包装了 Tiny C 编译器 (tcc) 以供 Tcl 使用。它可以用于
- 将 C 代码直接编译到内存中
- 生成动态加载库 (DLL) 或可执行文件。
便利函数生成包装代码,因此用户只需编写真正重要的 C 代码。
示例
将 C 函数“动态地”包装到 Tcl 命令中(此处在交互式会话中显示)
% package require tcc 0.2 % namespace import tcc::* % cproc sigmsg {int i} char* {return Tcl_SignalMsg(i);} % sigmsg 4 illegal instruction
生成一个带有快速实现的斐波那契数的 DLL
% set d [tcc::dll] % $d ccode { static int fib(int n) {return n <= 2? 1 : fib(n-1) + fib(n-2);} } % $d cproc fiboy {int n} int {return fib(n);} % $d write -name fiboy % load fiboy[info sharedlibextension] % fiboy 20 6765
生成一个带有额外的 square 命令的 tclsh
% set code [tcc::wrapCmd square {double x} double x_square {return x*x;}] % append code { int AppInit(Tcl_Interp *interp) { int rc; rc = Tcl_CreateObjCommand(interp,"square",x_square,NULL,NULL); return Tcl_Init(interp); } int main(int argc, char *argv[]) { Tcl_Main(argc, argv, AppInit); return 0; } } % tcc $::tcc::dir exe t % t add_file $::tcc::dir/c/crt1.c % t add_library tcl8.5 % t compile $code % t output_file mytclsh.exe % exec mytclsh.exe {<<puts [square 5]} 25.0
Tcltcc 是开源的,LGPL 许可的,可从 http://code.google.com/p/tcltcc/ 获取。在当前早期阶段(2007 年 10 月),完整的功能仅在 Windows 95/XP 平台上可用,但内存中编译在 Linux 上也可以工作。
tDOM
[edit | edit source]tDOM 是一个用于 XML/HTML 处理的流行扩展,它允许 SAX 风格的“即时”解析和 DOM 方法,在内存中表示整个 XML 元素。
这是一个 SAX 风格应用程序的例子。随 tDOM 附带的 expat 解析器使用回调来处理元素开始、字符数据和处理指令。元素、属性、字符和处理指令都进行了计数,此外还对每种元素类型进行了计数。
#!/usr/bin/env tclsh
package require tdom
#--- Callbacks for certain parser events
proc el {name attlist} {
global g
incr ::nEl
incr ::nAtt [llength $attlist]
inc g($name)
}
proc ch data {
incr ::nChar [string length $data]
}
proc pi {target data} {
incr ::nPi
}
proc inc {varName {increment 1}} {
upvar 1 $varName var
if {![info exists var]} {set var 0}
incr var $increment
}
#--- "main" loop
if ![llength $argv] {puts "usage: $argv0 file..."}
foreach file $argv {
foreach i {nEl nAtt nChar nPi} {set $i 0} ;# reset counters
array unset g
set p [expat -elementstartcommand el \
-characterdatacommand ch \
-processinginstructioncommand pi ]
if [catch {$p parsefile $file} res] {
puts "error:$res"
} else {
puts "$file:\n$nEl elements, $nAtt attributes, $nChar characters,\
$nPi processing instructions"
foreach name [lsort [array names g]] {
puts [format %-20s%7d $name $g($name)]
}
}
$p free
}