用tcl中的单个变量替换几行命令

时间:2015-06-05 15:35:01

标签: tcl tk

我知道我一直在问很多问题,但我还在学习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
}

2 个答案:

答案 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生成三个不同的值,存储在cntlenf中。有几种方法可以让命令过程返回多个值,但这里最干净的解决方案是让它返回一个值;要打印的列表。可以使用单个命令从该列表计算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有点令人困惑,因为它通常允许对非正式字符串的数据结构进行字符串操作(如字符串替换)。这使得语言非常强大和富有表现力,但也意味着新手并不总能得到常规类型系统给予他们的胫骨。

在这种情况下,您通过从文件中读取字符串然后在其上使用listFromFilesplit内创建了一个列表结构。从那时起它就是一个列表,你应该只对它执行列表操作。如果您想要删除数据中的所有逗号,您应该对列表中的每个项目执行该操作,或者在拆分文本之前在listFromFile中执行操作。

列表上的字符串操作会起作用,但有时结果会出现乱码,因此应避免混合它们。另一个好处是,在这种情况下,string map优于regsub,如果没有其他任何东西,它会使代码更清晰。

文档:forforeachlindexllengthlsearchlsortproc,{{3 }},putsregsubsetsplitstring

答案 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]]
}