基本上,我有一个由多个空格分隔的单词组成的字符串.然而,事情是,可以有多个空格而不是只有一个分隔单词.这就是为什么[split]
不做我想要的:
split "a b"
Run Code Online (Sandbox Code Playgroud)
给我这个:
{a {} {} {} b}
Run Code Online (Sandbox Code Playgroud)
而不是这个:
{a b}
Run Code Online (Sandbox Code Playgroud)
在搜索Google时,我在Tcler的wiki上找到了一个页面,用户在那里提出了大致相同的问题.
一个建议的解决方案看起来像这样:
split [regsub -all {\s+} "a b" " "]
Run Code Online (Sandbox Code Playgroud)
这似乎适用于简单的字符串.但是测试字符串如[string repeat " " 4]
(使用字符串重复,因为StackOverflow剥离多个空格)将导致regsub
返回"",这split
将再次分成{{} {}}
而不是空列表.
另一个提议的解决方案是这个,强制重新解释给定字符串作为列表:
lreplace "a list with many spaces" 0 -1
Run Code Online (Sandbox Code Playgroud)
但是,如果有一件事我已经了解了TCL,那就是你永远不应该l
在字符串上使用列表函数(以...开头).事实上,这个会阻塞包含特殊字符的字符串(即{和}):
lreplace "test \{a b\}"
Run Code Online (Sandbox Code Playgroud)
返回test {a b}
而不是test \{a b\}
(这将是我想要的,每个以空格分隔的单词分成结果列表的单个元素).
另一种解决方案是使用"过滤器":
proc filter {cond list} {
set res {}
foreach element $list {if [$cond $element] {lappend res $element}}
set res
}
Run Code Online (Sandbox Code Playgroud)
然后你会像这样使用它:
filter llength [split "a list with many spaces"]
Run Code Online (Sandbox Code Playgroud)
同样,同样的问题.这会调用llength
一个字符串,它可能包含特殊字符(同样,{和}) - 传递它"\ {ab \}"会导致TCL抱怨"列表中无法匹配的开括号".
我设法通过修改给定的filter
函数来使它工作,在if中的$ cond前面添加一个{*},所以我可以使用它string length
代替llength
,这似乎适用于我试图使用的每个可能的输入到目前为止.
这个解决方案现在可以安全使用吗?它到目前为止我没有测试一些特殊的输入吗?或者说,是有可能做到这一点的权利在一个简单的方法?
Don*_*ows 15
最简单的方法是使用regexp -all -inline
选择并返回所有单词.例如:
# The RE matches any non-empty sequence of non-whitespace characters
set theWords [regexp -all -inline {\S+} $theString]
Run Code Online (Sandbox Code Playgroud)
相反,如果您将单词定义为字母数字序列,则将其用于正则表达式术语: {\w+}