• 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, hacker news

    Recent posts on blogs I like:

    Streaming the Biden Infrastructure Plan

    I streamed my thoughts about the Biden infrastructure plan, and unlike previous streams, I uploaded this to YouTube. I go into more details (and more tangents) on video, but, some key points: Out of the nearly $600 billion in the current proposal that is …

    via Pedestrian Observations April 11, 2021

    Collections: Clothing, How Did They Make it? Part IVb: Cloth Money

    This is the second half of the fourth part of our four part (I, II, III, IVa) look at the production of textiles, particularly wool and linen, in the pre-modern world. Last time, we looked at commercial textile workers and the finishing processes for text…

    via A Collection of Unmitigated Pedantry April 9, 2021

    Notes from “Don’t Shoot the Dog”

    I just finished Karen Pryor’s “Don’t Shoot the Dog: the New Art of Teaching and Training.” Partly because a friend points out that it’s not on Audible and therefore she can’t possibly read it, here are the notes I took and some thoughts. It’s a quick, eas…

    via The whole sky April 2, 2021

    more     (via openring)


  • Posts
  • RSS
  • ◂◂RSS
  • Contact