我知道我一直在问很多问题,但我还在学习tcl,到目前为止我还没有发现任何类似于这个问题的东西。是否可以用一个变量function0
代替tcl中的set f命令?
我希望能够替换以下代码;
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
}
答案 0 :(得分:3)
变量用于存储值。要隐藏(封装)某些代码行,您需要使用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有点令人困惑,因为它通常允许对非正式字符串的数据结构进行字符串操作(如字符串替换)。这使得语言非常强大和富有表现力,但也意味着新手并不总能得到常规类型系统给予他们的胫骨。
在这种情况下,您通过从文件中读取字符串然后在其上使用listFromFile
在split
内创建了一个列表结构。从那时起它就是一个列表,你应该只对它执行列表操作。如果您想要删除数据中的所有逗号,您应该对列表中的每个项目执行该操作,或者在拆分文本之前在listFromFile
,中执行操作。
列表上的字符串操作会起作用,但有时结果会出现乱码,因此应避免混合它们。另一个好处是,在这种情况下,string map
优于regsub
,如果没有其他任何东西,它会使代码更清晰。
文档:for,foreach,lindex,llength,lsearch,lsort,proc,{{3 }},puts,regsub,set,split,string
答案 1 :(得分:1)
(更多的是评论而非答案,但我想要格式化)
要注意的一件事:$ f包含列表,然后在其上使用字符串命令regsub
,然后将regsub
的结果视为再次列出。
将list命令与列表值一起使用。我用
替换了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]]
}