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

Replace several lines of commands with a single variable in tcl

我知道我问了很多问题,但我仍在学习 tcl,到目前为止我还没有发现任何与此问题类似的问题。例如,是否可以用一个变量 function0 替换 tcl 中的一组 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
}

变量是用来存储值的。要隐藏(封装)某些代码行,您需要一个命令过程,您可以使用 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 中。有几种方法可以使命令过程 return 具有多个值,但这里最简洁的解决方案是使它 return 成为单个值;您要打印的列表。 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
}

这就是为什么我没有费心去创建一个过程returning 三个值:你真的只需要一个。


glenn jackman 在另一个关于使用 regsub 的回答中提出了一个非常好的观点(实际上是两点)。为了完整起见,我将在这里重复。

Tcl 有点令人困惑,因为它通常允许对非正式字符串的数据结构进行字符串操作(如字符串替换)。这使得该语言非常强大和富有表现力,但也意味着新手并不总是像常规类型系统那样受到打击。

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

列表上的字符串操作可以,但有时结果会出现乱码,因此应避免混合使用。另一个好处是,在这种情况下,string mapregsub 更可取,如果不出意外的话,它会使代码更清晰一些。

文档:for, foreach, lindex, llength, lsearch, lsort, proc, puts, regsub, set, split, string, while

(评论多于答案,但我想要格式)

需要注意一点:$f持有一个列表,然后你在上面使用字符串命令regsub,然后你对待[=的结果12=] 再次作为列表。

使用带有列表值的列表命令。我会将 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]]
}