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

Bash Argument Parsing and Quoting

October 4th, 2016
bash, tech  [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:

High-Speed Rail in Small, Dense Countries

Four years ago I brought up the concept of the small, dense country to argue in favor of full electrification in Israel, Belgium, and the Netherlands. Right now I am going to dredge up this concept again, in the context of intercity trains. In a geographi…

via Pedestrian Observations October 12, 2019

What do executives do, anyway?

An executive with 8,000 indirect reports and 2000 hours of work in a year can afford to spend, at most, 15 minutes per year per person in their reporting hierarchy... even if they work on nothing else. That job seems impossible. How can anyone make any im…

via apenwarr September 29, 2019

Taxing investment income is complicated

How should a state tax investment income if it wants to maximize its citizens’ welfare? This sounds like a simple question but I find it surprisingly hard to think about. Here are some of the positions I’ve moved through over the last few years: Taxing in…

via The sideways view September 22, 2019

more     (via openring)

More Posts:


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