some user
some user

Reputation: 1008

How do I use Tcl to puts string containing curly bracket { and }?

I am writing code to generate Tcl script, it generates script that includes "puts {blah}".

But the script will fail if I try to puts { or }. I thought the escape is '\' but it didn't work:

% puts {}}
extra characters after close-brace
% puts {\}}
\}
% puts {\{}
\{

puts{{} also does not work but puts{{}} works.

Similarly, if \ is the last character of the string, the command will not complete.

I have checked the 12 rules of Tcl (http://www.tcl.tk/man/tcl8.5/TclCmd/Tcl.htm) but I don't see a solution to my problem.

Upvotes: 0

Views: 3866

Answers (4)

RAVI507
RAVI507

Reputation: 129

% puts \{\}\}
{}}
% puts \{\{\}
{{}
% puts this\ is\ it\ {\}\}
this is it {}}

This may help you I just used the concept of the @Peter Lewerin

Upvotes: 0

Donal Fellows
Donal Fellows

Reputation: 137787

Braces can quote most things, but cannot quote unbalanced braces. That's when you have to stop using braces for quoting and do it all with backslashes (which can quote anything, but which are annoying and ugly). Indeed, that's what Tcl's own list-quoting engine does.

# Double quotes can quote things in some cases.
set a "This is{ an example"
set b "and so }is this"
puts [list $a $b]
This\ is\{\ an\ example and\ so\ \}is\ this

If you're generating commands, you're strongly advised to use list to do it, or the equivalent code at the C level, which is hooked in behind Tcl_NewListObj() and friends. It gets this sort of thing right so you don't have to. (It also has some performance optimisations when it comes to execution as a bonus.)

Upvotes: 2

Peter Lewerin
Peter Lewerin

Reputation: 13282

If you are going to read an input stream that might contain unbalanced braces and use the text on that stream for scripted output you are going to have to either a) count braces and balance them somehow, or b) use double quotes. If the input stream contains double quote characters it's quite easy to string map them to escaped double quotes.

You might also get some mileage out of the list command, which is quite clever with escaping. If your input is foo }bar [baz], stored in the variable foo, you can use the command puts [list puts $foo] to output the script

puts foo\ \}bar\ \[baz\]

which reproduces the input.

Another solution, if noone needs to read the generated scripts, is to convert every character into a character code, so that foo} bar becomes e.g. \x66\x6f\x6f\x7d\x20\x62\x61\x72 (which can be output directly). One can of course exclude alphanumerics from this conversion to preserve some readability. The main point of this exercise is that you don't need any quoting at all.

There are probably more elegant methods as well, but without knowing your data it's hard to make good suggestions.

Upvotes: 0

Dinesh
Dinesh

Reputation: 16436

As per rule, braces should be balanced and anything placed in between braces will be treated literally. These are the ones causing this behaviour for you.

% puts "{"
{
% puts "}"
}
% puts "{{}"
{{}
% 

Use double quotes for enclosing the string.

Upvotes: 0

Related Questions