Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to support string contains unpaired " and {

0 views
Skip to first unread message

robeson

unread,
Sep 29, 2008, 10:35:24 PM9/29/08
to
As I know,
if string contains " , we should use { } to quote:
>set var {"}
if string contains { , we should use " " to quote:
>set var "{"
But I encounter some problems:
1. if use:
>set var "{"
when i want to lappend it or list it, the value is changed
> list $var
\{

the \ is added before {, that change the value of string
2. how could i support a string like 123{"456 ??

Anybody could help me ?

Donald Arseneau

unread,
Sep 29, 2008, 10:57:58 PM9/29/08
to
On Sep 29, 7:35 pm, robeson <junfei...@live.cn> wrote:
> As I know,
> if string contains " , we should use { } to quote:>set var {"}
> if string contains { , we should use " " to quote:>set var "{"
> 2. how could i support a string like 123{"456 ??

Use quotes and a backslash

set var "123{\"456"

Note that such quoting problems don't happen for data read in from
input
sources, just from explicit strings in the source code.

> 1. if use:>set var "{"
>
> when i want to lappend it or list it, the value is changed
> list $var
> \{

Don't use strings as lists, and don't use lists as strings!

Many strings do not correspond to any valid list, so don't
use strings as lists in case you get a program error.

Multiple strings can correspond to a particular list, so
Tcl has to arbitrarily choose a particular string when
converting a list to a string, so don't use lists as strings
if you care about having a particular string result.

If you really want lists, build them properly and extract the
string elements using lindex.

If you want a string, then use [append] or [concat], not
[lappend].

Donald Arseneau as...@triumf.ca

robeson

unread,
Sep 29, 2008, 11:13:21 PM9/29/08
to
> Donald Arseneau                            a...@triumf.ca

Thanks for information but our codes have too much lappend/list
operation, Maybe I have to put { } " to the restriction set ...

oak...@bardo.clearlight.com

unread,
Sep 29, 2008, 11:25:26 PM9/29/08
to

The solution is straight-forward and simple - don't use list
operations on strings. Really, that's all there is to it. If you try
to treat a string as a list, tcl will attempt to convert that string
to a list, and in doing so may add additional characters to the string
representation to preserve the new list format of the data.That is how
Tcl is designed to work.

There is no way to avoid that, other than to simply avoid treating
strings as lists.

The answer to your specific question of how to "support a string like
123{"456" is the same answer -- only use string operations on it and
you'll be fine. Use either curly braces or double quotes and add
backslashes where necessary when creating the original data. Of
course, if the data is in a file or comes from a stream, there's
nothing special you have to do to support it (except, again, don't
treat it as a list)

robeson

unread,
Sep 29, 2008, 11:39:27 PM9/29/08
to

Thanks, it seems "avoid" being the only solution ...

Andreas Leitgeb

unread,
Sep 30, 2008, 3:39:28 AM9/30/08
to
robeson <junf...@live.cn> wrote:
>>  set var "123{\"456"
>> [...]

> Thanks for information but our codes have too much lappend/list
> operation, Maybe I have to put { } " to the restriction set ...

There is *nothing wrong* with e.g.
set lst [list $var]
lappend lst $var ;# add it again, as a second item

You just shouldn't have any expectations regarding what
$lst then looks like, itself, except that both
[lindex $lst 0] and [lindex $lst 1]
give you back your original string.

Ralf Fassel

unread,
Sep 30, 2008, 5:13:52 AM9/30/08
to
* robeson <junf...@live.cn>

| if string contains " , we should use { } to quote:
| >set var {"}
| if string contains { , we should use " " to quote:
| >set var "{"

A different approach is to use \ to quote the individual 'offenders':

set var 123\{456
set var 123\"456
set var 123\{\"456

| 1. if use:
| >set var "{"
| when i want to lappend it or list it, the value is changed
| > list $var
| \{
| the \ is added before {, that change the value of string

No, the value of the string (and the new list element) is not changed,
it only looks like that because the printed representation of the list
chose to use the 'other' way to quote the single "{" character.
You used double quotes, the list representation uses a backslash.
(The "{" needs to be quoted, otherwise it would look like the start of a
list instead of a single list element containing of the single char "{".)

set var \{
=> {
set l [list $var]
=> \{

If you extract the just-added list element, you will find it is still
one char, not two:

lindex $l 0
=> {
string length [lindex $l 0]
=> 1

Same thing with lappend. Don't get fooled by the printed
representation of a list, it needs to include the necessary quoting in
case you convert the list to string and back, and which form of
quoting it uses depends. Most of the times it is backslash, sometimes
it is curly braces

set var " "
=>
lappend l $var
=> { }

See? You used "", the list representation uses {} to enclose the
string, but the string itself is not changed.

string length [lindex $l 0]
=> 1

Now, as others have pointed out, it is wise *not* to use strings as
lists and vice versa. I.e. do *not*
set var \{
llength $var
=> error: unmatched open brace in list

It is safe to use strings as list *elements* though.



| 2. how could i support a string like 123{"456 ??

Use backslash quotes for the individual characters, see above.

HTH
R'

Larry W. Virden

unread,
Sep 30, 2008, 9:18:17 AM9/30/08
to

> operation, Maybe I have to put { } " to the restriction set ...- Hide quoted text -
>
> - Show quoted text -

If you have too many list operations on the strings, then that means
those strings need to be lists from the beginning.

So, you have to live with the \ before the {.

You will need to either do the set via

set var [list 123\{\"456]
or
set var "123{\"456"
set var [split $var]


However, in both cases, you are going to end up with
123\{\"456
as the contents of $var.

Your only other alternative is to change those list commands to be
string commands instead.

Larry W. Virden

unread,
Sep 30, 2008, 9:21:48 AM9/30/08
to
On Sep 30, 9:18 am, "Larry W. Virden" <lvir...@gmail.com> wrote:
>
> set var [list 123\{\"456]
> or
> set var "123{\"456"
> set var [split $var]
>
> However, in both cases, you are going to end up with
> 123\{\"456
> as the contents of $var.

Well, of course, it depends on how you access var. If you access it as
a list, then you are going to see:
$ tclsh8.5
% set var [list "123{\"456"]
123\{\"456
% llength $var
1
% string length [lindex $var 0]
8
% string length $var
10
% puts $var
123\{\"456
% puts [lindex $var 0]
123{"456

So you have to be careful when you are doing this that you are
accessing the string accordingly.

sleb...@gmail.com

unread,
Sep 30, 2008, 5:54:42 PM9/30/08
to

I think you may be getting the wrong advice. You've mentioned that
your code has lots of [lappend] and [list] which seems to indicate to
me that the original author knew what he was doing: don't use string
commands to create lists (he's using list commands correctly). Your
problem seems to be that you are then accessing this well constructed
list as a string - which may or may not do what you want.

Larry have shown you above how to read the list properly. CAREFULLY
NOTE that your observation that "{" is changed to "\{" is NOT TRUE.
The string "{" is still "{". It's only "\{" in the string
representation OF THE LIST, not the string itself.

Example:

set var "{"
set foo [list $var]
puts $foo ;# prints "\{"
puts [lindex $foo 0] ;# prints "{"

robeson

unread,
Oct 4, 2008, 12:00:09 AM10/4/08
to junf...@alcatel-sbell.com.cn
On Oct 1, 5:54 am, "slebet...@yahoo.com" <slebet...@gmail.com> wrote:

> On Sep 30, 11:39 am,robeson<junfei...@live.cn> wrote:
>
>
>
> > On Sep 30, 11:25 am, oak...@bardo.clearlight.com wrote:
>

Thanks for the information, it make me a little more clearer about how
tcl works :-)
I can make a conclusion that though the real value of string contains
{ or " is not changed when list, it is still NOT allowed to use
lappend for string which contains { ".
Bad news is this conclusion will still make { " the restriction for my
codes.
Thanks all for kindly help.

robeson

unread,
Oct 4, 2008, 12:02:17 AM10/4/08
to
> Your only other alternative is to change those list commands to be
> string commands instead.

I think this will be the only solution

Gerald W. Lester

unread,
Oct 4, 2008, 7:54:01 PM10/4/08
to
robeson wrote:
>... it is still NOT allowed to use
> lappend for string ...

Stop!

You should never use lappend on a string -- only a list.

Use append on strings -- and never on list.

--
+------------------------------------------------------------------------+
| Gerald W. Lester |
|"The man who fights for his ideals is the man who is alive." - Cervantes|
+------------------------------------------------------------------------+

Kevin Kenny

unread,
Oct 4, 2008, 9:43:00 PM10/4/08
to
Gerald W. Lester wrote:
> robeson wrote:
>> ... it is still NOT allowed to use
>> lappend for string ...
>
> Stop!
>
> You should never use lappend on a string -- only a list.
>
> Use append on strings -- and never on list.

More precisely:

Everything is a string.
Corollary: All lists are strings.
In fact, a list is a string that the list parser accepts.

The value of the variable passed to [lappend] must be a list;
otherwise [lappend] will fail.

When [lappend] succeeds, the value left in the variable
is a list.

A list can contain any string (including, of course,
another list) as a member. Hence, the arguments to [lappend]
beyond the first may be arbitrary strings (and, of course,
may be lists).

The value of the variable passed to [append] may be any
string. The values passed as the remaining arguments may
also be arbitrary strings.

[append] does not fail (short of memory exhaustion).

After [append] succeeds, the value left in the variable
is a string. It may or may not be a list. In particular,
there are many combinations in which [append]ing a string
to a list assigns the variable to a string that is not a list.

Hence, if you need a list in a variable, it is unwise
to use [append].

It's convenient to use shorthand thinking:

Everything is a string. It's ok to use a list as
a string. It's not ok to use a string as a list
unless the string is known to be a list.

If I saw a string in the source code, and it follows list
syntax, it is a list.

If it's the result of [list], [lappend], [lreplace],
[lrange], etc. (the commands that are documented to
produce lists), then it is a list.

If it's produced in other way than appearing in
the source code or being constructed by a command
that yields a list, it may not be assumed to be
a list. (At least, not without further proof.)

--
73 de ke9tv/2, Kevin

Khamis Abuelkomboz

unread,
Oct 5, 2008, 7:45:44 AM10/5/08
to robeson
Hi

Tcl does not change strings nor lists, as long as you keep eye of what is list and what is a string.
problems occur only, if tcl is forced to translate from string to list.

if you want to translate a string to a list, it must be "well formatted" and mappable to list. refer
to tcl documentation here.
This means, if the string contains unmasked "{", tcl tries here to begin a list value, that assumes
to have a closing "}".
Tcl converts strings to lists by using the eval logic, as example
set lst [eval list $string]

so assume string has the value of "a b c \{ \"" and you want to iterate on the string using the
following command:
foreach x $string { do something }

the upove command will fail, because "{" and "\"" don't have matching closing characters.

the other way (list ==> string) will allways work, as example

set lst [list a b c "{" "\""]
append string "any value"

greating
khamis

robeson schrieb:


--
Try Code-Navigator on http://www.codenav.com
a source code navigating, analysis and developing tool.
It supports following languages:
* C/C++
* Java
* .NET (including CSharp, VB.Net and other .NET components)
* Classic Visual Basic
* PHP, HTML, XML, ASP, CSS
* Tcl/Tk,
* Perl
* Python
* SQL,
* m4 Preprocessor
* Cobol

0 new messages