基本上,我有一个由多个空格分隔的单词组成的字符串。然而,问题是,可以有多个空格,而不仅仅是一个分隔单词。这就是为什么[split]
不做我想做的事:
split "a b"
给了我这个:
{a {} {} {} b}
而不是这个:
{a b}
搜索 Google,我在 Tcler 的 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
,这似乎适用于我尝试使用的每个可能的输入到目前为止。
这个解决方案现在可以安全使用吗?它会不会因为我到目前为止没有测试过的一些特殊输入而窒息?或者,是否有可能以更简单的方式做到这一点?