::  Posts  ::  RSS  ::  ◂◂RSS  ::  Contact

Bash Argument Parsing and Quoting

October 4th, 2016
tech, bash  [html]
There are many ways in which 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
For example, consider the following set of strings, separated by line breaks:
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

Recent posts on blogs I like:

I’m Giving a Talk About Construction Costs Tomorrow

By popular demand, I’m giving the talk I gave 2 weeks ago at NYU, again. The database will be revised slightly to include more examples (like Ukraine, which I added between when I gave the talk and when I blogged about it), and I may switch around a few t…

via Pedestrian Observations December 2, 2019

Your room can be as bright as the outdoors

The effect was huge: I became dramatically more productive between 3:30pm and whenever I turned off the light. I estimate the lamp bought me between half an hour and two hours a day, depending on how overcast it was.

via benkuhn.net November 26, 2019

git-subtrac: all your git submodules in one place

Long ago, I wrote git-subtree to work around some of my annoyances with git submodules. I've learned a lot since then, and the development ecosystem has improved a lot (shell scripts are no longer the best way to manipulate git repos? Whoa!). Thus, I …

via apenwarr November 24, 2019

more     (via openring)

More Posts:


  ::  Posts  ::  RSS  ::  ◂◂RSS  ::  Contact