diff options
Diffstat (limited to 'doc/el_substitute.html')
-rw-r--r-- | doc/el_substitute.html | 309 |
1 files changed, 309 insertions, 0 deletions
diff --git a/doc/el_substitute.html b/doc/el_substitute.html new file mode 100644 index 0000000..4da03f5 --- /dev/null +++ b/doc/el_substitute.html @@ -0,0 +1,309 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> + <meta http-equiv="Content-Language" content="en" /> + <title>execline: variable substitution</title> + <meta name="Description" content="execline: variable substitution" /> + <meta name="Keywords" content="execline variable substitution el_substitute" /> + <!-- <link rel="stylesheet" type="text/css" href="http://skarnet.org/default.css" /> --> + </head> +<body> + +<p> +<a href="index.html">execline</a><br /> +<a href="http://skarnet.org/software/">Software</a><br /> +<a href="http://skarnet.org/">skarnet.org</a> +</p> + +<h1> Variable substitution </h1> + +<p> + In a shell, when you write +</p> +<pre> + $ A='foobar' ; echo $A +</pre> +<p> + the <tt>echo</tt> command is given the argument <tt>foobar</tt>. +The <tt>foobar</tt> <em>value</em> has been substituted for the +<tt>A</tt> <em>variable</em>. +</p> +<p> + Although <tt>execline</tt> maintains no state, and thus has no +real variables, it provides such a <em>substitution</em> facility +via <em>substitution commands</em>, namely: +</p> +<ul> + <li> <a href="define.html">define</a> </li> + <li> <a href="import.html">import</a> </li> + <li> <a href="importas.html">importas</a> </li> + <li> <a href="elglob.html">elglob</a> </li> + <li> <a href="elgetpositionals.html">elgetpositionals</a> </li> + <li> <a href="multidefine.html">multidefine</a> </li> + <li> <a href="multisubstitute.html">multisubstitute</a> </li> +</ul> + +<p> + A substitution command takes a <em>key</em>, i.e. a string +(which can contain any character but <tt>$</tt>, <tt>{</tt> and +<tt>}</tt>, although it is recommended to use only alphanumerical +characters), and a way to compute a <em>value</em>. +</p> + +<h2> Basics </h2> + +<ul> + <li> If the substitution key is <em>foo</em>, then the substitution +command will look for every occurrence of <tt>${<em>foo</em>}</tt> or +<tt>$<em>foo</em></tt> in the rest of its argv. Note that +<tt>${<em>foo</em>}bar</tt> matches, but <tt>$<em>foo</em>bar</tt> +<strong>does not</strong>. To be safe, always use the syntax with +braces, unless <tt>$<em>foo</em></tt> is a word on its own. </li> + <li> Every match is then replaced with the <em>value</em>. </li> +</ul> + +<p> +The simplest example is the following: +</p> + +<pre> +#!/command/execlineb +define FOO blah +echo $FOO +</pre> + +<p> + which will replace the <tt>FOO</tt> key with the <tt>blah</tt> value, +then execute the <tt>echo</tt> command. So that script will print +<tt>blah</tt> on stdout. +</p> + +<a name="quoting" /> +<h2> Quoting </h2> + +<p> + execline allows you to write literal <tt>${<em>foo</em>}</tt> constructs +even when the <em>foo</em> variable is being substituted, thanks to a +quoting mechanism. + Brace (pun intended) yourself: the following is the most complex part +of the whole language. +</p> + +<h3> Rationale </h3> + +<p> + If we want to be able to have a literal <tt>${<em>foo</em>}</tt>, then: +</p> +<ul> + <li> The <tt>${<em>foo</em>}</tt> sequence will mean one of two things: +be substituted, or <em>don't</em> be substituted. </li> + <li> The default (unquoted) action should be: substitute. </li> + <li> A sequence that means "do not substitute" should be able +to appear literally. The quote character should also be able to +appear literally before a sequence that means "substitute". (Tricky, eh ?) </li> + <li> There should be as few quote characters as possible, to avoid +shell-like quoting nightmares. </li> +</ul> + +<h3> Syntax </h3> + +<p> + Rule: +</p> + +<ul> + <li> The backslash (<tt>\</tt>) is a quote character for substitution commands. </li> + <li> The following rule applies only if the <em>foo</em> key is +explicitly used in a substitution command. If no command tries to +substitute anything for <em>foo</em>, sequences like +<tt>${<em>foo</em>}</tt> and preceding backslashes are left untouched. </li> + <li> (Substitute.) If <tt>${<em>foo</em>}</tt> is preceded by <tt>2*n</tt> backslashes +(an <strong>even</strong> number), the whole sequence will be +replaced with <tt>n</tt> backslashes, followed by the substituted value. </li> + <li> (Do not substitute.) If <tt>${<em>foo</em>}</tt> is preceded by <tt>2*n+1</tt> backslashes +(an <strong>odd</strong> number), the whole sequence will be replaced +with <tt>n</tt> backslashes, followed by the literal <tt>${<em>foo</em>}</tt>. </li> +</ul> + +<p> + And now, the catch: the <a href="execlineb.html">execlineb</a> launcher, +as well as the shell, +interprets backslashes as escape characters. To make a word that contains +a backlash, you need to write <em>two</em> backslashes in your execline +script or shell command line. That means that the whole number of backslashes +you must write before your <tt>${<em>foo</em>}</tt> sequence must be doubled +for the substitution command to read the proper number of backslashes and +perform its work correctly. <br /> + Once you keep that in mind, the quoting rule is logical. +</p> + +<h3> Example </h3> + +<p> + The quoting rule is best illustrated with the following example, where +the <tt>A</tt> key is substituted, and the <tt>$B</tt> sequences mean +nothing special. +</p> + +<pre> +#!/command/execlineb +define A val +foreground { echo $A \\$A \\\\$A \\\\\\$A \\\\\\\\$A \\\\\\\\\\$A } + echo $B \\$B \\\\$B \\\\\\$B \\\\\\\\$B \\\\\\\\\\$B +</pre> +<p> + prints +</p> +<pre> +val $A \val \$A \\val \\$A +$B \$B \\$B \\\$B \\\\$B \\\\\$B +</pre> + +<p> + Phew. +</p> + +<a name="el_transform"> +<h2> Value transformations </h2> +</a> + +<p> + A value can go through +<a href="el_transform.html">several transformations</a> before it is +substituted. It can be <a href="el_transform.html#crunch">crunched</a>, +<a href="el_transform.html#chomp">chomped</a>, and/or +<a href="el_transform.html#split">split</a>. +</p> + +<a name="split"> +<h2> Substitution of split values </h2> +</a> + +<p> + A <a href="el_transform.html">split</a> value for <tt>FOO</tt> means that +a word containing <tt>${FOO}</tt> will be replaced by zero, one, or +(usually) more than one word. The value actually means a +<em>list</em> of values. +</p> + +<p> + The rule is: substituting a list of values +(<em>v1</em>, <em>v2</em>, <em>...</em>) for a key <em>A</em> is the +same as listing the substitutions of every value <em>v<tt>i</tt></em> +for <em>A</em>. <br /> + For instance, +</p> + +<pre> +#!/command/execlineb +define -s FOO "v1 v2 v3" echo prefix-${FOO}-postfix +</pre> + +<p> + will substitute three values for <tt>$FOO</tt>: <tt>v1</tt>, <tt>v2</tt> +and <tt>v3</tt>. So the <tt>echo</tt> command will be called with three +arguments: <tt>prefix-v1-postfix</tt>, <tt>prefix-v2-postfix</tt>, and +<tt>prefix-v3-postfix</tt>. +</p> + +<p> +(Implementation note: the fact that word prefixes are kept is +what makes execline's subtitutions secure. +<a href="el_semicolon.html">Blocks</a> are implemented via prefix +space characters; a substitution occurring inside a block will always produce +words beginning with the right amount of spaces, thus substituted +values cannot prematurely terminate a block.) +</p> + +<a name="recursive" /> +<h3> Recursive substitutions </h3> + +<p> + 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 +</p> + +<pre> +#!/command/execlineb +define -s B "1 2 3" echo ${B}x${B} +</pre> +<p> + the <tt>${B}x${B}</tt> word will be replaced with <em>nine</em> words: +<tt>1x1</tt>, <tt>1x2</tt>, <tt>1x3</tt>, <tt>2x1</tt>, <tt>2x2</tt>, +<tt>2x3</tt>, <tt>3x1</tt>, <tt>3x2</tt>, and <tt>3x3</tt>, in that order. +<br /> Here is an example with two distinct substitutions in parallel: +</p> + +<pre> +#!/command/execlineb +multisubstitute +{ + define -s A "a b c d" + define -s B "1 2 3" +} +echo ${A}x${B} +</pre> + +<p> + The <tt>${A}x${B}</tt> word will be replaced with <em>twelve</em> words: +<tt>ax1</tt>, <tt>ax2</tt>, <tt>ax3</tt>, <tt>bx1</tt>, <tt>bx2</tt>, +<tt>bx3</tt>, <tt>cx1</tt>, <tt>cx2</tt>, <tt>cx3</tt>, <tt>dx1</tt>, +<tt>dx2</tt>, and <tt>dx3</tt>, in that order. You can check that the +order of the <tt>define</tt> directives in +<a href="multisubstitute.html">multisubstitute</a> does not matter. +</p> + +<p> +If the left-to-right order does not suit you, then you should perform +<em>serial</em> substitutions. For instance, the previous script can +be replaced with +</p> + +<pre> +#!/command/execlineb +define -s B "1 2 3" +define -s A "a b c d" +echo ${A}x${B} +</pre> +<p> + and will substitute <tt>${B}</tt> first, then <tt>${A}</tt>. So it +will print +</p> + +<pre> +ax1 bx1 cx1 dx1 ax2 bx2 cx2 dx2 ax3 bx3 cx3 dx3 +</pre> + +<p> + in that order. +</p> + +<a name="brainfsck"></a> +<h2> Not for the faint of heart </h2> + +<p> + If you think you have mastered the art of execline substitution, then +you can try to do better than these people: +</p> + +<ul> + <li><a href="http://jriou.org/">Joël Riou</a> +wrote the <a href="quine-jriou.txt">first execlineb quine</a>, using +only <tt>echo</tt> as non-execline external command. </li> + <li> Shortly after, <a href="http://code.dogmap.org/">Paul Jarc</a> +wrote a <a href="quine-prj.txt">much shorter quine</a>, using +<tt>echo</tt> and <tt>env</tt> as non-execline external commands. He +also wrote a <a href="quine-prj-2.txt">revised version</a>, using only +<tt>echo</tt>, and a shorter <a href="quine-prj-3.txt">definitive +version</a>. The last one is probably very close to the shortest +possible execline quine. </li> + <li> <a href="http://www.madore.org/~david/">David Madore</a> +wrote <a href="quine-dam.txt">another quine</a>, using <tt>printf</tt>. +His quine is longer than the other ones, but is well-commented and can +be used as a tutorial on how to write quines. :) </li> +</ul> + +</body> +</html> |