【发布时间】:2012-11-03 01:44:29
【问题描述】:
基本上,我有一个由多个空格分隔的单词组成的字符串。然而,问题是可以有多个空格,而不是只有一个分隔单词。这就是为什么[split] 没有做我想做的事:
split "a b"
给我这个:
{a {} {} {} b}
而不是这个:
{a b}
在 Google 上搜索,我找到了a page on the Tcler's wiki,其中一位用户提出了或多或少相同的问题。
建议的解决方案如下所示:
split [regsub -all {\s+} "a b" " "]
这似乎适用于简单的字符串。但是像 [string repeat " " 4] 这样的测试字符串(使用字符串重复,因为 StackOverflow 去除了多个空格)将导致 regsub 返回“”,split 将再次拆分为 {{} {}} 而不是一个空列表。
另一个建议的解决方案是这个,强制将给定字符串重新解释为列表:
lreplace "a list with many spaces" 0 -1
但是,如果我从 TCL 中了解到一件事,那就是您永远不应该在字符串上使用列表函数(以 l 开头)。事实上,这会阻塞包含特殊字符(即 { 和 })的字符串:
lreplace "test \{a b\}"
返回test {a b} 而不是test \{a b\}(这正是我想要的,每个以空格分隔的单词都拆分为结果列表的一个元素)。
另一个解决方案是使用“过滤器”:
proc filter {cond list} {
set res {}
foreach element $list {if [$cond $element] {lappend res $element}}
set res
}
然后你会像这样使用它:
filter llength [split "a list with many spaces"]
同样的问题。这将在字符串上调用llength,该字符串可能包含特殊字符(同样,{ 和}) - 传递它“\{ab\}”会导致 TCL 抱怨“列表中不匹配的左大括号”。
我设法通过修改给定的 filter 函数,在 if 中的 $cond 前面添加一个 {*} 来使其工作,所以我可以将它与 string length 一起使用而不是 llength,这似乎为我迄今为止尝试使用的所有可能的输入工作。
这个解决方案现在可以安全使用吗?它会不会因为我到目前为止没有测试过的一些特殊输入而窒息?或者,是否有可能以更简单的方式正确做到这一点?
【问题讨论】: