bash-hackers-wiki/original_source/snipplets/wrapperargs.txt

88 lines
2.2 KiB
Plaintext
Raw Permalink Normal View History

====== Generate code with own arguments properly quoted ======
---- dataentry snipplet ----
snipplet_tags: arguments, quoting, escaping, wrapper
LastUpdate_dt: 2010-07-31
Contributors: Jan Schampera
type: snipplet
----
^ Keywords: | arguments,escape,quote,wrapper,generate |
^ Contributor: | self |
There are situations where Bash code needs to generate Bash code. A script that writes out another script the user or cron may start, for example.
The general issue is easy, just write out text to the file.
A specific detail of it is tricky: If the generated script needs to call a command using the arguments the first original script got, you have problem in writing out the correct code.
I.e. if you run your generator script like
<code>./myscript "give me 'some' water"</code>
then this script should generate code that looks like
<code>echo give me 'some' water"</code>
you need correct escapes or quotes to not generate shell special characters out of normal text (like embedded dollar signs ''$'').
**__Solution:__**
A loop over the own arguments that writes out properly quoted/escaped code to the generated script file
There are two (maybe more) easy options:
* writing out singlequoted strings and handle the embedded singlequotes
* the [[commands:builtin:printf | printf command]] knows the ''%q'' format specification, which will print a string (like ''%s'' does), but with all shell special characters escaped
===== Using singlequoted string =====
<code>
#!/bin/bash
# first option:
# generate singlequoted strings out of your own arguments and handle embedded singlequotes
# here to call 'echo' in the generated script
{
printf "#!/bin/bash\n\n"
printf "echo "
for arg; do
arg=${arg/\'/\'\\\'\'}
printf "'%s' " "${arg}"
done
printf "\n"
} >s2
</code>
The generated script will look like:
<code>
#!/bin/bash
echo 'fir$t' 'seco "ond"' 'thir'\''d'
</code>
===== Using printf =====
The second method is easier, though more or less Bash-only (due to the ''%q'' in printf):
<code>
#!/bin/bash
{
printf "#!/bin/bash\n\n"
printf "echo "
for arg; do
printf '%q ' "$arg"
done
printf "\n"
} >s2
</code>
The generated script will look like:
<code>
#!/bin/bash
echo fir\$t seco\ \"ond\" thir\'d
</code>