title: How to split a string into a list of words in TCL, ignoring multiple spaces?
body: <p>Basically, I have a string that consists of multiple, space-separated words. The thing is, however, that there can be multiple spaces instead of just one separating the words. This is why <code>[split]</code> does not do what I want:</p>
  
  <pre><code>split "a    b"
  </code></pre>
  
  <p>gives me this:</p>
  
  <pre><code>{a {} {} {} b}
  </code></pre>
  
  <p>instead of this:</p>
  
  <pre><code>{a b}
  </code></pre>
  
  <p>Searching Google, I found <a href="http://wiki.tcl.tk/1499" rel="noreferrer" title="[split] discussion">a page on the Tcler's wiki</a>, where a user asked more or less the same question.</p>
  
  <p>One proposed solution would look like this:</p>
  
  <pre><code>split [regsub -all {\s+} "a    b" " "]
  </code></pre>
  
  <p>which seems to work for simple string. But a test string such as <code>[string repeat " " 4]</code> (used string repeat because StackOverflow strips multiple spaces) will result in <code>regsub</code> returning " ", which <code>split</code> would again split up into <code>{{} {}}</code> instead of an empty list.</p>
  
  <p>Another proposed solution was this one, to force a reinterpretation of the  given string as a list:</p>
  
  <pre><code>lreplace "a   list   with many   spaces" 0 -1
  </code></pre>
  
  <p>But if there's one thing I've learned about TCL, it is that you should never use list functions (starting with <code>l</code>) on strings. And indeed, this one will choke on strings containing special characters (namely { and }):</p>
  
  <pre><code>lreplace "test    \{a b\}"
  </code></pre>
  
  <p>returns <code>test {a b}</code> instead of <code>test \{a b\}</code> (which would be what I want, every space-separated word split up into a single element of the resulting list).</p>
  
  <p>Yet another solution was to use a 'filter':</p>
  
  <pre><code>proc filter {cond list} {
      set res {}
      foreach element $list {if [$cond $element] {lappend res $element}}
      set res
  }
  </code></pre>
  
  <p>You'd then use it like this:</p>
  
  <pre><code>filter llength [split "a   list   with many   spaces"]
  </code></pre>
  
  <p>Again, same problem. This would call <code>llength</code> on a string, which might contain special characters (again, { and }) - passing it "\{a b\}" would result in TCL complaining about an "unmatched open brace in list".</p>
  
  <p>I managed to get it to work by modifying the given <code>filter</code> function, adding a {*} in front of $cond in the if, so I could use it with <code>string length</code> instead of <code>llength</code>, which seemed to work for every possible input I've tried to use it on so far.</p>
  
  <p>Is this solution safe to use as it is now? Would it choke on some special input I didn't test so far? Or, is it possible to do this <em>right</em> in a simpler way?</p>