execline
Software
www.skarnet.org
In a shell, when you write
$ A='foobar' ; echo $A
the echo command is given the argument foobar. The foobar value has been substituted for the A variable.
Although execline maintains no state, and thus has no real variables, it provides such a substitution facility via substitution commands, namely:
A substitution command takes a key, i.e. a string (which can contain any character but $, { and }, although it is recommended to use only alphanumerical characters), and a way to compute a value.
The simplest example is the following:
#!/command/execlineb define FOO blah echo $FOO
which will replace the FOO key with the blah value, then execute the echo command. So that script will print blah on stdout.
When a substitution for foo was requested, execline-0.x did not allow a literal $foo or ${foo} to appear in the argv - everything was substituted no matter what. execline-1.y allows it... at a price.
If we want to be able to have a literal ${foo}, then:
Rule:
And now, the catch: the execlineb and
execline launchers, as well as the shell,
interpret backslashes as escape characters. To make a word that contains
a backlash, you need to write two backslashes in your execlineb
script or shell command line. That means that the whole number of backslashes
you must write before your ${foo} sequence must be doubled
for the substitution command to read the proper number of backslashes and
perform its work correctly.
If you keep that in mind, the quoting rule should be easy to remember and use.
The quoting rule is best illustrated with the following example, where the A key is substituted, and the $B sequences mean nothing special.
#!/command/execlineb define A val foreground { echo $A \\$A \\\\$A \\\\\\$A \\\\\\\\$A \\\\\\\\\\$A } echo $B \\$B \\\\$B \\\\\\$B \\\\\\\\$B \\\\\\\\\\$B
prints
val $A \val \$A \\val \\$A $B \$B \\$B \\\$B \\\\$B \\\\\$B
A value can go through several transformations before it is substituted. It can be crunched, chomped, and/or split.
A split value for FOO means that a word containing ${FOO} will be replaced by zero, one, or (usually) more than one word. The value actually means a list of values.
The rule is: substituting a list of values
(v1, v2, ...) for a key A is the
same as listing the substitutions of every value vi
for A.
For instance,
#!/command/execlineb define -s FOO "v1 v2 v3" echo prefix-${FOO}-postfix
will substitute three values for $FOO: v1, v2 and v3. So the echo command will be called with three arguments: prefix-v1-postfix, prefix-v2-postfix, and prefix-v3-postfix.
(Note for those who follow: the fact that word prefixes are kept is what makes execline-1.y secure. Blocks are implemented via prefix tildas; a substitution occurring inside a block will always produce words beginning with the right amount of tildas, thus substituted values cannot prematurely terminate a block. So there.)
A direct consequence of that rule is that substitutions will be performed recursively if more than one key appears in one word and the values for those keys are split. Parallel substitutions are performed from left to right. For instance, in
#!/command/execlineb define -s B "1 2 3" echo ${B}x${B}
the ${B}x${B} word will be replaced with nine words:
1x1, 1x2, 1x3, 2x1, 2x2,
2x3, 3x1, 3x2, and 3x3, in that order.
Here is an example with two distinct substitutions in parallel:
#!/command/execlineb multisubstitute { define -s A "a b c d" define -s B "1 2 3" } echo ${A}x${B}
The ${A}x${B} word will be replaced with twelve words: ax1, ax2, ax3, bx1, bx2, bx3, cx1, cx2, cx3, dx1, dx2, and dx3, in that order. You can check that the order of the define directives in multisubstitute does not matter.
If the left-to-right order does not suit you, then you should perform serial substitutions. For instance, the previous script can be replaced by
#!/command/execlineb define -s B "1 2 3" define -s A "a b c d" echo ${A}x${B}
and will substitute ${B} first, then ${A}. So it will print
ax1 bx1 cx1 dx1 ax2 bx2 cx2 dx2 ax3 bx3 cx3 dx3
in that order.
If you think you have mastered the art of execline substitution, then you can try to do better than these people: