Forum OpenACS Q&A: Translation of vars within string

Ok, here is a simple one that I don't get...

I have a string that I store in a database
field and want to interpert the variables
within that string when rendered on a webpage.

Say I have this string which
I just got out of the db as $hello

    Hi, My name is $first_names last_name.

When I put $hello into the output html
within a tcl page, the variables within it
don't get interperted.

I want the result to be:

    Hi, My name is Bob OConnor

Instead of:

    Hi, My name is $first_names $last_name.

Thanks for your help!
-Bob

Collapse
Posted by Don Baccus on
Check out Tcl's "subst" command ...
Collapse
Posted by David Walker on
I've never noticed the subst command.  I'm glad to know about it.

I'm using ns_adp_parse with the format "Hi, My name is
<%=$first_names%> <%=$last_name%>."

Collapse
Posted by MaineBob OConnor on

Ok, in tclsh I can

% set x 1
1
% set y "you are the $x!"
you are the 1!
% subst {$y}
you are the 1!
% set y
you are the 1!

This works but so does set, but within
my tcl program and using this format:

<p>[subst $y]

No substitution is done...

And I want to avoid David's solution <%=$first_names%> because I want "mere users" to be able to enter a few variables in a text string that gets stored in the db and later select and substitute with the current value of, for instance $name. in the string to render on the page.... (clear?)

-Bob

Collapse
Posted by David Walker on
This was successful for me.
set x {my name is $name}
set name David

ns_write [subst $x]
Collapse
Posted by Michael A. Cleverly on
And I want to avoid David's solution <%=$first_names%> because I want "mere users" to be able to enter a few variables in a text string that gets stored in the db and later select and substitute with the current value of, for instance $name. in the string to render on the page.... (clear?)
If that's the case, make sure you read the man page for subst, specifically the -nocommands switch. Otherwise some malicious user could save as their string: "Goodbye $first_names $last_name. [exec rm -r -f /]. Have a nice day. [ns_shutdown]", which probably wouldn't be something you'd want.

And, just for kicks, say you only wanted certain variables to be substituted. (So that $first_name doesn't blow up.) You could use Tcl 8's very handy string map:

set html [string map [list $first_names $first_names $last_name $last_names $foo $foo] $user_string_from_database]
(I hope the backslashes above make it or the code will look positively stupid. 😊
Collapse
Posted by David Walker on
Here. With the backslashes escaped. (and $last_names changed to $last_name)
(ignore the email version of this message)
set html [string map [list $first_names $first_names $last_name $last_name $foo $foo] $user_string_from_database]
Collapse
Posted by MaineBob OConnor on

David, it was my typo (in the stuffed var names and yes,

[subst $y]
does work, thanks Don. I was testing this in a proc in /tcl and this process is slow because aolserver must be restarted each time.

I was also thinking that giving users access to vars was perhaps a bad idea. It seems like undefined vars don't throw an error if in a /tcl/ proc. But Michael has made a *most* convincing security argument. String maps look like a great solution and maybe I'll use something other than a $... In another thread Jerry Asher suggested this format ::name::. I was thinking maybe [name] would work as something simple... that would be [name] in the string map. That's one backslash depending on how you see this message!

-Bob