我知道我一直在问很多问题,但我仍然在学习tcl,我还没有发现任何类似的问题到目前为止。是否有可能将tcl中的一组命令替换为一个变量function0
?
我希望能够替换下面的代码;
set f [listFromFile $path1]
set f [lsort -unique $f]
set f [lsearch -all -inline $f "test_*"]
set f [regsub -all {,} $f "" ]
set len [llength $f]
set cnt 0
使用变量function0
,因为相同的代码在脚本中多次出现。我应该提一下,它既出现在proc
中,也出现在proc
中
上面的代码与
的脚本相似while {$cnt < $len} {
puts [lindex $f $cnt]
incr cnt
after 25; #not needed, but for viewing purposes
}
变量用于存储值。为了隐藏(封装)一些代码行,您需要使用proc
命令定义一个命令过程。
您想隐藏以下行
set f [listFromFile $path1]
set f [lsort -unique $f]
set f [lsearch -all -inline $f "test_*"]
set f [regsub -all {,} $f "" ]
set len [llength $f]
set cnt 0
能够调用例如function0 $path1
并一举完成所有这些计算。此外,您希望在代码中使用调用过程的结果,如下所示:
while {$cnt < $len} {
puts [lindex $f $cnt]
# ...
这意味着您希望function0
生成三个不同的值,分别存储在cnt
、len
和f
中。有几种方法可以让命令过程返回多个值,但这里最简洁的解决方案是让它返回单个值;要打印的列表。len
中的值可以通过一个命令从该列表中计算出来,cnt
的初始化最好在命令过程之外执行。你得到的是:
proc function0 path {
set f [listFromFile $path]
set f [lsort -unique $f]
set f [lsearch -all -inline $f test_*]
set f [regsub -all , $f {}]
return $f
}
可以这样使用:
set f [function0 $path1]
set len [llength $f]
set cnt 0
while {$cnt < $len} {
puts [lindex $f $cnt]
incr cnt
after 25; #not needed, but for viewing purposes
}
或者像这样:
set f [function0 $path1]
set len [llength $f]
for {set cnt 0} {$cnt < $len} {incr cnt} {
puts [lindex $f $cnt]
after 25; #not needed, but for viewing purposes
}
或者像这样:
set f [function0 $path1]
foreach item $f {
puts $item
after 25; #not needed, but for viewing purposes
}
这就是为什么我没有创建一个返回三个值的过程:你只需要一个。
glenn jackman在另一个关于regsub
使用的回答中提出了一个非常好的观点(实际上是两个观点)。为了完整起见,我在这里重复一遍。
Tcl有点令人困惑,因为它通常允许对不是正式字符串的数据结构进行字符串操作(如字符串替换)。这使得该语言非常强大和富有表现力,但也意味着新手并不总是得到常规类型系统所给予的那种刺激。
在本例中,通过从文件中读取字符串,然后对其使用split
,在listFromFile
中创建了一个列表结构。从这一点来看,它是一个列表,你应该只对它执行列表操作。如果您想去掉数据中的所有逗号,您应该对列表中的每个项目执行该操作,或者在分割文本之前在listFromFile
中执行操作。
对列表的字符串操作可以工作,但有时结果会乱码,因此应避免混合使用它们。另一个优点是,在这种情况下,string map
比regsub
更可取,如果没有别的,它使代码更清晰。
文档:for, foreach, lindex, llength, lsearch, lsort, proc, puts, regsub, set, split, string, while
(与其说是回答,不如说是评论)
有一点需要注意:$f保存一个列表,然后对它使用字符串命令regsub
,然后将regsub
的结果再次视为列表。
使用列表命令和列表值。我会用
替换regsub命令set f [lmap elem $f {string map {"," ""} $elem} ]
对于Tcl 8.5或更早版本,您可以这样做:
for {set i 0} {$i < [llength $f]} {incr i} {
lset f $i [string map {, ""} [lindex $f $i]]
}