[ is a syntactical element of Tcl that directs the interpreter to perform script substitution (a.k.a. command substitution).

It also happens to be impossible to search for this page or to link to it from any other wiki page :)

AMG: Link to it using one of the following syntaxes:


Unfortunately, this means back references will not be recorded.

Line continuation and embedded comments

AMG: [ is part of an alternative line continuation syntax that does not insert a space. If the script substitution (i.e. all the text between [ and ]) consists entirely of whitespace (including newline) and/or comment, it is replaced with empty string. This is useful when a very long string needs to be broken across multiple lines, yet the string must not have any spaces. It might also be handy to embed comments, though it's usually easier to just put the comments above the line of code.

For example:

puts this_is_a_really_long_string_that_[
puts this_string_has_a_[
# comment!



Remember that comments terminate with newline (when not preceded by an odd number of backslashes) or with end-of-input, not with ]. Therefore, this does not allow for same-line embedded comments. "puts a[#comment]b" fails because ]b is part of the comment, leaving the interpreter wanting a ] to close the script substitution. Though, if you're really desperate, exploit nested [eval] and the above end-of-input rule:

puts what_is_in_[eval {#this is a comment}]this_string

Be mindful that this notation is not available within brace-quoted strings, unless of course the string is to be evaluated as a Tcl script. It does, however, work with double-quoted strings, and certainly with the list command. The important thing is that the context must allow script substitutions.

Unfortunately, this notation cannot be used to add embedded comments to expr. It evaluates to empty string, which is a value on which expr will want to operate.

As of Tcl 8.6.10, there is a performance penalty for the above. Extra strcat bytecodes are emitted to concatenate the substrings, including the interstitial empty strings. It costs even more to use [eval] as shown above. Use tcl::unsupported::disassemble to see this:

% tcl::unsupported::disassemble script {puts this_string_has_a_[
# comment!
ByteCode 0x0x2348810, refCt 1, epoch 17, interp 0x0x22c7ac0 (epoch 17)
  Source "puts this_string_has_a_[\n# comment!\n        ]secret_i..."
  Cmds 1, src 65, inst 13, litObjs 4, aux 0, stkDepth 4, code/src 0.00
  Commands 1:
      1: pc 0-11, src 0-64
  Command 1: "puts this_string_has_a_[\n# comment!\n        ]secret_i..."
    (0) push1 0         # "puts"
    (2) push1 1         # "this_string_has_a_"
    (4) push1 2         # ""
    (6) push1 3         # "secret_in_the_middle"
    (8) strcat 3
    (10) invokeStk1 2
    (12) done
% tcl::unsupported::disassemble script {puts what_is_in_[eval {#this is a comment}]this_string}
ByteCode 0x0x2331120, refCt 1, epoch 17, interp 0x0x22c7ac0 (epoch 17)
  Source "puts what_is_in_[eval {#this is a comment}]this_string"
  Cmds 2, src 54, inst 17, litObjs 5, aux 0, stkDepth 4, code/src 0.00
  Commands 2:
      1: pc 0-15, src 0-53        2: pc 4-9, src 17-41
  Command 1: "puts what_is_in_[eval {#this is a comment}]this_string"
    (0) push1 0         # "puts"
    (2) push1 1         # "what_is_in_"
  Command 2: "eval {#this is a comment}..."
    (4) push1 2         # "eval"
    (6) push1 3         # "#this is a comment"
    (8) invokeStk1 2
    (10) push1 4         # "this_string"
    (12) strcat 3 
    (14) invokeStk1 2 
    (16) done

It should be possible to optimize this if people actually start using this notation. For example, string cat is already optimized:

% tcl::unsupported::disassemble script {string cat a b c}
ByteCode 0x0x2348a10, refCt 1, epoch 17, interp 0x0x22c7ac0 (epoch 17)
  Source "string cat a b c"
  Cmds 1, src 16, inst 3, litObjs 1, aux 0, stkDepth 1, code/src 0.00
  Commands 1:
      1: pc 0-1, src 0-15
  Command 1: "string cat a b c"
    (0) push1 0         # "abc"
    (2) done