Hacker Newsnew | past | comments | ask | show | jobs | submitlogin
Bash Argument Parsing and Quoting (2016) (jefftk.com)
36 points by luu on March 5, 2020 | hide | past | favorite | 14 comments


Bash is a great argument for the fact that it is not so much the features of the language that matter, but what ecosystem it is a part of. Bash is popular because it is the default scripting language of the shell in Unix. Javascript is popular because it is in all the browsers. C is popular because it is the default compiled language of Unix. Objective-C became popular because it was the default programming language of the iPhone.


Yeah this explains why and predicts that Kotlin and Swift are popular, because Android and iOS now use them.

It also explains PHP, because PHP was tightly integrated with Apache via shared library, and in the 90's, lots of hosting providers were spinning up LAMP.

So basically if you wanted to buy hosting in the 90's, you could pay $20/month for shared PHP, or $200/month for a dedicated box running Perl.

PHP creator Rasmus had a good talk about that recently. So shared hosting was essentially "remote OS" that was cheap.

-----

Exceptions to the rule: Python and Ruby. People installed them because they were nicer languages, and mainly used them on the server side. But Python even made it to the client side in many instances because people like the language! (Dropbox, IPython/Jupyter, etc.)

bash was the default on Linux, which was huge. Other Unixes like Solaris and BSDs used other shells, but yeah it does seem true that bash was helped along by Linux.

I think Linus said that bash was literally the first program that ever ran on Linux, which made sense. Before that I guess bash was run on Solaris and commercial Unixes, and wasn't that popular.


> Replace \ with \\, ' with \', and wrap each argument in 's if it contains anything suspicious.

This is not a correct way to do shell quoting.

The code doesn't quite follow this description, but it's not correct either:

    $ tmp=$(printf '\nX')
    $ newline=${tmp%X}
    $ printf '['; quote "$newline"; printf ']\n'
    [
    
    ]

    $ quote 'foo+\bar'
    'foo+\\bar'


The easiest way to quote for the shell:

* Add ' at the beginning and end

* Replace internal ' with '\''

This is because inside '-quoted string only ' itself has special semantics.

> wrap each argument in 's if it contains anything suspicious.

Such vague advice is wrong in all contexts.


I wouldn't rely on a manual mean, considering that there is a built-in API:

    printf '%q' <string_to_quote>


Related to quoting, Oil has a way to opt out of needing it everywhere, which I documented here:

Simple Word Evaluation in Unix Shell

http://www.oilshell.org/release/latest/doc/simple-word-eval....

parsing and evaluation aren't interleaved, and code and data aren't confused

No Implicit Splitting, Dynamic Globbing, or Empty Elision

Opt In to the Old Behavior With Explicit Expressions

Also related: Oil Doesn't Confuse Flags and Files http://www.oilshell.org/blog/2020/02/dashglob.html


If you want to parse complicated strings using only a POSIX tool, and put the results into an array, you're better off using Awk.


Why not use bash's printf %q?

   string=$(printf ' %q' "${array[@]}")


In Bash ≥ 4.4, you can also use parameter transformations:

    function quote() {
      echo "${@@Q}"
    }
(In both cases, the generated output is understood bash, but not necessarily by other POSIX-compliant shells.)


When writing bash scripts, I use shellcheck.net to help find problems like this. It's great!


I could never imagine building an arg parser with bash. But A brilliant solution I must say :p


shellcheck. It's great. Use it.

It has plugins for most IDEs, and just reading the wiki entries for the error messages you encounter will teach you a lot of useful things about bash.


came here to say this!


Does `getopts` not handle this?




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: