BASH is weird

For very basic stuff, BASH is decently simple and intuitive, for example variables are set with the format name=value and they’re referenced with $name1. However, that changes once you start diving deeper (as I had to do for my Linuxgraphy by Strabo presentation). An example which illustrates my point would be:

myvar=($(echo A B C))
myvar=1234
echo $((myvar += 46)) ${myvar[${myvar:0:1}]}

It has 3 things which really bothered me:

  1. The output of $(echo A B C) is replaced “literally”, and then the whole expression is evaluated. Meaning, myvar=($(echo A B C)) turns into myvar=(A B C), which creates an array with those three letters.

    I thought the “returned” value of $(echo A B C) would be the whole string “A B C”, so the array would have one element, that string. However, $() isn’t really a function, which takes arguments, “creates” commands and returns their output. It’s Command Substitution, the text gets executed and it’s output replaces the $(...) itself (slightly reminiscent of LISP macros).

    Side note: obviously, the original expected behaviour can happen if we use some quotes:

    myvar=("$(echo A B C)")
    
  2. On the second line, myvar becomes an integer and then we do an arithmetic operation on it, nothing wrong here. ${parameter:offset:length} returns the substring from parameter from offset with size length, but we’re giving it a “number”, so it should either throw some sort of error or return something default, like 0. However it correctly returns the number 1 (and no, that isn’t a default, the number is correctly parsed as a string).

    This shows that numbers are actually strings too, and numerical operations are just weird string operations. Contrary to any dynamically-typed language, it’s not like the type of a variable is inferred from it’s value, there isn’t a type at all! Which makes everything even more weird, considering you can create variables with a specific type.

  3. Finally, the arguably biggest weirdness of it all, is ${myvar[1]}. It doesn’t matter how it is represented, at first myvar was the list of values A, B, C and now it’s a number, this should return nothing. Per contra, the value B is returned instead!

    Via trial and error, we find that our number will be returned when the index is 0, and with index 2 we get C. So all variables are arrays, and by default for integer and string operations, the first value is used?

    This is strange, but it cannot be the full picture, because names have attributes, alongside it’s type, a variable (name) can be read-only, but also have the “trace” flag, which only works with functions. So, variables and functions are the same “object”? Unfortunately, I couldn’t find any definitive information on the topic, so this train of thought will have to be left unresolved.

And this is just one example, more bizarreness can be found with square brackets and most ok looking code. Some people even go as far to say:

Its syntax is insane, incredibly error prone, its defaults are awful, and it’s not a real big person programming language.

But I believe that is a step too far, there are benefits, especially when approaching it seriously. Every language has mind-numbing oddities, some get the out of the way from the start (like BASH), and others much later.


  1. Of course this is just one of the many ways to reference and work with variables.