【问题标题】:How to split a string into a list of words in TCL, ignoring multiple spaces?如何将字符串拆分为 TCL 中的单词列表,忽略多个空格?
【发布时间】: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,这似乎为我迄今为止尝试使用的所有可能的输入工作。

这个解决方案现在可以安全使用吗?它会不会因为我到目前为止没有测试过的一些特殊输入而窒息?或者,是否有可能以更简单的方式正确做到这一点?

【问题讨论】:

    标签: string split tcl


    【解决方案1】:

    您可以改用正则表达式: 来自tcl wiki split

    按空格分割:陷阱

    split { abc def  ghi}
    {} abc def {} ghi
    

    通常,如果您按空格分割并且不想要那些空白字段,那么您最好这样做:

    regexp -all -inline {\S+} { abc def  ghi}
    abc def ghi
    

    【讨论】:

      【解决方案2】:

      最简单的方法是使用regexp -all -inline 选择并返回所有单词。例如:

      # The RE matches any non-empty sequence of non-whitespace characters
      set theWords [regexp -all -inline {\S+} $theString]
      

      如果您将单词定义为字母数字序列,则可以将其用于正则表达式术语:{\w+}

      【讨论】:

      猜你喜欢
      • 2015-09-14
      • 1970-01-01
      • 2023-01-22
      • 1970-01-01
      • 2022-07-29
      • 1970-01-01
      • 2021-04-28
      • 2022-01-18
      • 1970-01-01
      相关资源
      最近更新 更多