0

我在做 :

glob -nocomplain *

结果我得到了4个文件:

a b c d

如何从列表中删除b?我正在使用这个函数:

 proc lremove {args} {
     if {[llength $args] < 2} {
        puts stderr {Wrong # args: should be "lremove ?-all? list pattern"}
     }
     set list [lindex $args end-1]
     set elements [lindex $args end]
     if [string match -all [lindex $args 0]] {
        foreach element $elements {
            set list [lsearch -all -inline -not -exact $list $element]
        }
     } else {
        # Using lreplace to truncate the list saves having to calculate
        # ranges or offsets from the indexed element. The trimming is
        # necessary in cases where the first or last element is the
        # indexed element.
        foreach element $elements {
            set idx [lsearch $list $element]
            set list [string trim \
                "[lreplace $list $idx end] [lreplace $list 0 $idx]"]
        }
     }
     return $list
 }

但是它不适用于 glob 结果,而仅适用于字符串。请帮忙。

4

1 回答 1

2

这个lreplace过程相当狡猾,真的,交换顺序,ghetto 连接并string trim试图清理混乱。呸。这是一个更简单的版本(不支持-all,您不需要处理输出,glob因为这通常是唯一元素的列表):

proc lremove {list args} {
    foreach toRemove $args {
        set index [lsearch -exact $list $toRemove]
        set list [lreplace $list $index $index]
    }
    return $list
}

让我们测试一下!

% lremove {a b c d e} b d f
a c e

理论上它可以变得更高效,但它需要大量的工作并且是一个 PITA 来调试。这个版本更容易编写并且显然是正确的。它也应该比您使用的要快得多,因为它坚持纯粹的列表操作。


结果glob应该不是特别特别,需要任何不寻常的努力才能与它们一起工作,但是有一些非常令人讨厌的历史错误使得这并不总是正确的。最新版本的 8.4 和 8.5(即 8.4.20 和 8.5.15)没有这些错误。8.6 的任何发行版本(8.6.0 或 8.6.1)也没有。如果某些东西表现得很神秘,我们会询问版本并告诉您不要落后于时代......</p>

于 2013-10-10T08:00:20.120 回答