Tcl DISCUSSION

Tcl list breaks when an element contains spaces or braces: how should I build and read lists?

Started by mohamoud Tcl listslappendlist commandsplit stringargument expansion
5 replies 248 views 6 participants
Latest activity · 30 Sep 2026

Tcl list breaks when an element contains spaces or braces: how should I build and read lists?

mohamoud Tcl Forum
#1

My script collects source files with set files "$files $f" in a loop and later runs foreach f $files. It broke as soon as one path was C:/My Projects/top.v: that file shows up as two elements. In another script, foreach word $line on lines read from a log file stops with unmatched open brace in list.

I assumed a list was just a space-separated string. What is a Tcl list really, and what is the right way to build one and to break text into one?

Community replies 5

Re: Tcl list breaks when an element contains spaces or braces: how should I build and read lists?

#2

A list is a string with a defined syntax: elements are separated by whitespace, and an element that itself contains whitespace or special characters must be protected with braces or backslashes. String concatenation does not add that protection, so "$files $f" with your path produces text that parses as two elements, C:/My and Projects/top.v.

Build lists only with list commands. lappend files $f appends the value as exactly one element, adding quoting as needed; afterwards llength $files is 1 and the string form is {C:/My Projects/top.v}. list $a $b $c creates a list from values in the same safe way.

Re: Tcl list breaks when an element contains spaces or braces: how should I build and read lists?

#3

The second error is the reverse mistake: treating arbitrary text as a list. A log line containing a lone { or an odd quote is not valid list syntax, and foreach, lindex or llength will reject it. Convert text to a list explicitly with split $line, which accepts any string.

split breaks at every single separator character, so adjacent separators produce empty elements: split "a,,b" , has 3 elements, the middle one empty, and the same happens with repeated spaces. For whitespace-separated words use regexp -all -inline {\S+} $line, which returns just the non-blank fields.

Re: Tcl list breaks when an element contains spaces or braces: how should I build and read lists?

#4

The same discipline applies when a list becomes a command. To pass the elements of a list as separate arguments, use the expansion prefix: exec vlog {*}$files gives the compiler one argument per file, spaces intact, whereas exec vlog $files passes the whole list as a single argument. {*} needs Tcl 8.5 or later.

When you construct a script to run later, build it with list so each value stays one word: after 1000 [list puts $msg] works for any message, while after 1000 "puts $msg" breaks if the message has spaces or brackets.

Re: Tcl list breaks when an element contains spaces or braces: how should I build and read lists?

#5

Once values are real lists, the standard commands cover most needs: lindex $l 0 and lindex $l end for elements, lrange $l 1 end for a slice, lsearch -exact $l $x to find an index, lassign $pair name value to unpack (8.5 and later) and join $l ", " to turn a list back into display text.

Sorting has a useful option for signal and instance names. Plain lsort {x10 x9 x2} compares as text and gives x10 x2 x9; lsort -dictionary compares embedded numbers numerically and gives x2 x9 x10.

Re: Tcl list breaks when an element contains spaces or braces: how should I build and read lists?

#6

There is a performance side as well. Internally Tcl keeps a list as an array of elements, so lindex and llength are constant time and lappend is amortised constant time. Appending by string concatenation throws that representation away, and the next list command has to parse the whole string again, which makes a loop over n items quadratic. For a list of tens of thousands of nets or cells the difference is very noticeable.

For the same reason, avoid mixing string commands such as string length or append with list commands on the same large variable inside a loop.

TEP COMMUNITY