subst, a
built-in Tcl
command,
subtitutes variables and/or commands into a string.
Synopsis edit
-
- subst ?-nobackslashes? ?-nocommands? ?-novariables? string
Documentation edit
- official manpage
Description edit
subst performs the first stage of Tcl script evaluation, i.e.
variable substitution and/or command substitution, but stops short of evaluating the commands contained at the top level of the script.
According to
Joe English:
subst is massively handy in text-processing applications, especially
SGML and
XML down-translators.
subst and
string map make Tcl particularly well-suited for this type of task. Many jobs for which
Perl uses "right-hand-side" variables with
regular expression substitution, Tcl does as
REs whose results are subst-ituted.
Examples edit
Simple example of using
subst with XML/
HTML.
set html {<html><head>$title</head></html>}
set title "Hello, World!"
set output [subst -nocommands $html]
set output ;# -> <html><head>Hello, World!</head></html>
Another alternative would be to use
XPath Discussion edit
RS most often uses
subst for expanding
Unicodes: cross-platform, in mostly 8-bit environments, it is most robust to output Unicodes in the
\u.... notation - such snippets can be pasted into a text widget and visualized by
subst [$t get 1.0 end]
Variable Substitution edit
Even when the
-nocommands option is used, variable substitution triggers any command substitutions necessary to complete the variable substitution:
set var "code inclusion perverse \$tcl_platform(os\[puts OUCH!\])"
puts [subst -nocommands $var]
==> OUCH!
reference:
Eric Hassold, fr.comp.lang.tcl, 2008-12-30reference:
Tcl bug 536838-- Ok, I saw
Bug 536831 above. I think a
big warning should be inserted in the manual.
Lars H: What has Bug 536831 to do with this? I see nothing about -nocommands in that report.
The problem with
puts OUCH! rather seems to be that variable substitution can trigger command substitution in the array index part, or to put it differently, once one type of substitution has triggered,
subst has no control of what happens until that substitution is complete:
% subst -nobackslashes {$tcl_platform(threade\x64)\x64}
1\x64
A warning indeed seems appropriate.
What changed in Tcl 8.4.0 with regards to how subst treats break and continue during command substitution?
See Tcl Bug 536831,
Tcl Feature Request 684982, and the changes in the tests subst-10.*.
Without checking every byte, I think the incompatible changes are limited to those uses of
subst that attempt command substitution on a string that is not a syntactically valid Tcl script -- arguably something no script should be doing anyway.
Enhancement Suggestion: Hook for Variable Expansion edit
jcw 2004-05-03: It would be useful to extend
subst so it lets one catch variable accesses, and perhaps even command executions. What I mean is that when you
subst text with "... $var ..." then sometimes it is useful to be able to intercept the expansion, by turning it into a call such as
myhandler var for example, the result of which then gets used as substitution. The same (perhaps less important) might apply to
... [cmd ...] ... expansions.
This makes it simpler to implement tiny languages which also use
$var and
$var(item) as access mechanisms, but to things which are not necessarily stored in Tcl variables/arrays.
Would it be an idea to extend subst so it optionally passes each of its substitutions to a command? Could be a "-command ..." option, or simply the presence of more args.
DGP Am I missing something? Aren't you asking for variable and command
traces? Which exist?
D'oh! I'm missing that in this case you want to set a trace on a whole set of variables/commands whose names you do not know. OK, something to think about...
Anyhow, I think that's the right way to address the issue generally... add more types of traces that can be used everywhere. I'd be shy about diverging the implementation of
subst from the implementation of the substitution portion of normal script evaluation.
jcw: Yes, that's exactly the scenario.
subst on a string to expand names which are not known up front. Looks like there is no way to catch this right now. Perhaps some new "unknown traces" (or whatever terminology) would indeed be better. The key is to intercept between the parse for var/cmd expansions and the lookup for existing ones.
Parallel to double quoting edit
AMG: Am I correct in my understanding that:
[subst {anything at all}]
is always equivalent to:
"anything at all"
for absolutely any value of "anything at all"?
It occurred to me that if this is indeed the case, then maybe this equivalence could be the reason why backslash-newline-whitespace inside braces is replaced with a single space, in the interest of mirroring the way double quotes work. But then I experimented and found that
subst internally will do this replacement and does not need the Tcl interpreter to preprocess its input in this way.
PYK: Could you elaborate on what you mean by "internally will do this replacement"?
AMG:
subst internally replaces backslash-newline-whitespace with a single space. It's as simple as that. Here's a demonstration:
% subst abc\\\n\ \ def
abc def
See also edit
- eval
- regsub
- string map
- an extension to subst
- Template and Macro processing