Bash Argument Parsing and Quoting |
October 4th, 2016 |
bash, tech |
bash
is an awkward language, and
handling of arguments is certainly one of them. Here are two things
you might like to do in a shell:
- quoting: turn an array into a string, using shell-style escaping
- unquoting: turn a string into an array, interpreting shell-style escaping
argument1 argument two argument three argument='four and'There are multiple ways you could quote these as arguments, so here's one example:
argument1 "argument two" "argument three" "argument='four and'"Basically, I want Python's shlex, with its
quote
and split
, but I want it in bash
.
Unfortunately, bash
can't do this easily. What can you do?
Quoting you have to do yourself, but it's pretty straight-forward.
Replace \
with \\
, '
with \'
, and
wrap each argument in '
s if it contains anything suspicious.
Here's something that does this:
function quote() { first=true for arg in "$@"; do if $first; then first=false; else echo -n " "; fi if echo "$arg" | grep -q '[^a-zA-Z0-9./_=-]'; then arg="'$(echo "$arg" | sed -e 's~\\~\\\\~g' -e "s~'~\\\\'~g")'" fi echo -n "$arg" done echo }
Going the other way is both simpler and kind of evil. It turns out that the way you do this is:
eval unquoted=("$quoted")A warning though: if
quoted
contains things like $(echo
foo)
then they will be run. In many cases this isn't a problem,
but it's something to be aware of.
(I needed both of these when writing the automated installation script
for ngx_pagespeed. You need to be able to give it arguments to pass
through to nginx's ./configure
, and I wanted people to be
able to enter them exactly as they would on the command line. This
means I need to parse them into an array first. On the other hand, if
you're just using the script to set up ngx_pagespeed it needs to print
out a string that you should paste as ./configure
arguments,
which means I need quoting as well.)
[1] Which would actually need to work like read
and be passed
the name of a variable to put the array in, since you can't return
arrays in bash
.
Comment via: google plus, facebook, hacker news