The first example is not human readable, if the name of the function is a lie, I have no idea what this piece of code do :
trim_string() {
: "${1#"${1%%[![:space:]]*}"}"
: "${_%"${_##*[![:space:]]}"}"
printf '%s\n' "$_"
}The first example is not human readable, if the name of the function is a lie, I have no idea what this piece of code do :
trim_string() {
: "${1#"${1%%[![:space:]]*}"}"
: "${_%"${_##*[![:space:]]}"}"
printf '%s\n' "$_"
}I also think that a discussion about readability makes sense in a post about Bash. I don't personally program very often in Lua, Go or Ruby, but for the most part when I encounter code in these languages I don't find it very difficult to understand and modify. In contrast to this, every encounter with a significant amount of Bash seems to lead to a great deal of googling.
Here's how I'd write that function: trim_string() { python3 -c 'import sys; sys.stdout.write(sys.argv[1].strip())' "$1" }
If you're building something that multiple folks will be reading and using just call out to external processes and make it easier to follow what's going on. It's neat to know how to do these things, but they're honestly a bit of a security hole because a large portion of folks using them will never comprehend the why and how and just assume it's doing the proper what.
Also readability: While some of the examples may be somewhat confusing to someone who doesn't have a lot of Bash experience, to someone who does it can be a lot more readable then feeding a string in yet another language to an external program and processing the output..
Your definition of "reasonably complete" might not work for everyone else's use case.
Every explanation of why to use bash here seems like it's got a whole lot of constraints on when it's a good to use - I've finished some tasks just in bash scripts but when I'm writing something for anything other than one time passes it seems like more of a maintenance liability than anything else.
IMHO, spending the time to actually learn some bash can really improve one's CLI life. Bashing on bash seems mostly like a tired ol' trope, "If it's in bash, it's bad."
The author of the original article really has written some pretty shell code!
There are resource constraints even in large-ish embedded. Your main file system may live in a decent amount of flash space, but when the kernel is booting, it uses a tiny file system in RAM, which is pulled out of an initramfs image. There is a shell there with scripts.
The partition for storing the kernel image (with initramfs, device tree blobs and whatever else) might be pretty tight.
However, because a lot of these snippets depend on Bash extensions, they preclude the use of a smaller, lighter shell.
It is neat to discover functionality of bash I was unaware of by see folks push it to the limit though.
Just yesterday I was struck by the difference between if [[ ]]; and if [ ];
I didn't even bother grokking the difference in the end. I simply found something that worked and moved on with my day.
This is my understanding. Possibly not 100% correct but essentially correct enough for me to understand the reason/rationale for the difference.
It's certainly less readable than, say, my_str.strip()
The quotes don't function like the parens. If this were a two argument function, you wouldn't put one pair of quotes around the whole thing. They're clearly transforming the variable somehow, but I'm not sure how and/or why they're necessary.
I generally tell people that, once a script is longer than ~100 lines and/or you start adding functions, you're probably better off with something like Python.
I know that's not a popular opinion with shell enthusiasts, but it's saved me so much frustration both in writing new scripts and coming back to them later for refactoring.
Agreed. My threshold is usually "when you want to start using arrays or dictionaries". I find bash best for file manipulation and running programs in other languages
If you need >100 lines of code your code is too complex in the script world, and you should split it into several scripts where each does one thing, and that one thing well. Usually, bash scripts are applied with pipes. A sequence like cat x | tr a b | sort >output is much more likely and easy to handle then a single script which does all these things.
KISS with Bash is a very different approach compared to other scripting languages like Python and Perl. There you can write long code easily and conveniently. However, things can get tough when larger scripts need to be maintained.
I consider the examples in the "Bash Bible" a collection of useful black boxes. It's fine if they just work. Regarding the "unreadable" trim_string for instance, if you have problems to understand that code, and you have to change something then you can simply write your own new trim_string script, even in Python or Perl if you like. Pipes work also well with them.
Update: Another advantage of bash and pipes over Python/Perl is that the Unix system can assign each script in a pipe to a separate thread. That means, simple bash scripts with pipes can work _much_ faster than single scripts in Python or Perl.
I am curious if people will uptake PowerShell Core (though not much of a fan there either).
I never even bothered to learn Bash properly because even that's difficult, and I figured it'd be "good mental money after bad". And, now that Python ships with all distros, I feel even less need to.
I do like Bash's range syntax though:
for i in {0..5} ; do echo $i ; done
Like Ruby's. It's so nice! D: I lament Python's lack of it. echo {1..5}
is even nicer. Or echo {1..5}{1..5}{1..5}The practice of programming in shell languages was well established when Bash was designed and Bash was definitely designed with that use in mind. So by your definition Bash is a "real" programming language.
Lisp on the other hand, was much more designed as a system and formal notation to reason about certain classes of logic problems.. So, Lisp is not a "real" language?
No, it can not.
You can definitely tell there's a different "feel" to bash and Tcl, Python, Perl, Go, etc, yes? Shell languages basically evolved out of batch processing languages that were meant to only run programs in sequence and it shows.
In the past I almost exclusively used Python, but I'm starting to like Go.
String munging in Python is so much objectively easier to read than bash. I would say that it's because it is similar to a lot of the more popular languages than the sort of cryptic parameter substitution bash provides. And if that makes it easier to maintain some automation, then its worth the effort just to use Python IMO.
If people can't figure that out... I don't know how you're going to expect them to read a cryptic bash script.
Don't get me wrong there is totally some good use cases for bash. Init-scripts come to mind when you don't want to lug around a Python VM in a lightweight container, for example.
"How do we close a statement.... errr. Let's spell it backwards".
That's on the original Bourne shell and its author's evident love for Algol 68. Wikipedia has a fine summary.
Seems disingenuous to me. Java and Python are in a different class of readability than Bash or Perl.
Example: "abc" + "def" = "abcdef" vs "abc"."def" = "abcdef"
Would be better comparison if you would use whitespace in the other case as well. Which then makes it just as readable.
Also. "0" + "42" would that be "042" or 42? It may be better readable, but the semantics are unclear.
>>> 0 + 42
42
>>> "0" + "42"
'042'
>>> "0" + 42
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
>>> int("0") + 42
42 #!/bin/sh
FOO=" some long string here "
FOO="$( echo "$FOO" | sed -e ' s/^[[:space:]]//g; s/[[:space:]]$//g ' )"
This isn't "pure bash", but most of what I write in shell scripts isn't "pure bash". It's shell scripting: dirty, slow, easy, effective.Like any 'language', it takes on the complexity you put into it. English is really complicated, but you can also use a subset of it with only 850, 1200, or 2400 words, and suddenly it's very simple and clear.
Your example fails when $FOO is "-n", for instance. Also the g modifiers are redundant in your example since there's only one beginning of line per line and one end of line per line.
I would instead write this:
sed -r 's/^\s+|\s+$//g' <<< "$FOO"
EDIT: I think I see now what you probably thought would happen by using g, but no it wouldn't remove multiple spaces. So, you example also fails when $FOO is " x" (using 2 or more spaces at the ends).This is all from somebody who has just written a linux user space. Perhaps the author avoids shell as much as possible. It just isn't possible. I doubt it, though. Bash is awesome.
Let's use bash instead of a real programming language! It is super convenient! To do super fundamental things like trimming strings you just have to implement your own function with 40+ non-ASCII characters in a row! That example makes regexps seem like human readable and god knows if it is even correct or works portably across different versions of bash.
To be fair the article assumes you are first in bash and want to avoid launching subprocesses but for any production scripting that is the wrong hypothesis to begin with. A better approach would be to not start inside bash at all. Just do your scripting in a higher level language where basic ABC stuff like string, list, number and error handling are already there for you. Even if that trim_string function and everything else from the article would be provided in some bash-bible-std-lib it wouldn't even come close to what's available in say Python for example, and you still have to wrestle the syntax and other obscurities like -a (or -e) meaning file exists.
While there are some good examples in there if you are stuck in bash, this article was more of a 100 reasons not to use bash to me.
These scripts/snippets for me are just an unofficial extended standard lib
Then stop maintaining code from languages you don't understand. This is frustrating. I've seen solutions on the comments that call PYTHON! Are you effing kidding me? PYTHON ??
Granted, BASH docs aren't particularly succinct, but shell scripts are an absolute necessity in the OS world.
It's pretty simple: If you don't understand shellcode, don't maintain an OS, or rather, don't expect to be accommodated for lack of knowledge for something that's been standard for 30+ years.
https://www.gnu.org/software/bash/manual/html_node/Shell-Par...
My inner pedant has no comment regarding readability of Bash parameter expansions.
If we didn't have regexes we would have 100s of if/else's scattered all over program logic. That would be more hard to handle than the regex itself.