The Type System of Bash

Every programming language has a type system. The good ones make it explicit. And then there is Bash.


14 February 2020, by Boyang XiaAsk a question


Of all programming / scripting languages, the type system of Bash is probably the most obscure and even more error-prone than that of Perl. It is so inconspicuous that may people are misled to believe that Bash is "untyped". But like any language, Bash has its types.

The type system is very simple. There are only three of them: string, integers and, most importantly, lists. However, complexity arises due to two factors:

Latent typing. The type of a value is determined at runtime based on its context. Thus 1 can be either the integer 1 or the string "1".

Evaluation. Bash is very much like Lisp. And Bash expressions are, mostly, S-expressions. If you understand Lisp, then you understand Bash (and AST, stack machine and programming in general).

A S-expression is -- in simple layman's term -- a list where the first element is the function / command / programme, and the rest are the arguments.

echo Hello World        # echo is the function and it prints the two arguments,
                        # separated by one blank space, to the terminal.
echo Hello     World    # gives you the same result, the number of blank spaces
                        # inbetween does not matter.

In the above example, we have a list of three elements, echo, Hello and World, where echo is the function, returning its arguments Hello and World separated by one blank space.

If you want to print out "Hello     World" with the exact number of whitespaces, you have to put white spaces under single or double quotes to tell Bash that it is an argument, and not separator.

echo "Hello     World"        # echo gets one argurment.
echo  Hello  "   "   World    # echo gets three arguements -> same result.
echo Hello " " " "   World    # echo gets four arguments -> same result.

So in Bash everything is a list where the elements are separated by whitespaces (tab or space character). The element of a list can, depending on the context, be either a string, an integer or an expression that expands to elements.

A="Hello   World"   # Variable A is assigned the string "Hello   World".
echo $A             # The dollar operator $ expands the variable resulting
                    # effectively in: echo Hello   World

B="echo   Hello  World"
$B                  # The variable expands to the expression: echo   Hello  World
                    # which in turn is evaluated in the CLI.

You can also evaluate the result of a function with $( ... ) or `...`.

echo $( echo "Hello     World" )

The inner echo expands to Hello     World which in turn as arguments to the outer echo results in "Hello World".

Using $(( ... )) you can evaluate arithmetic expressions.

echo $(( 1 + "2" ))     # Quotes don't matter
echo $(( 2 ** 63 - 1 )) # maximum
echo $(( 2 ** 63 ))     # minimum
echo Hello $(( 8 / 4 )) # Within $((...)) integers are integers,
                        # and outside of it, they are strings.

However, there is no support for floating-point numbers.

echo $(( 1 ** 3.14 )) # -> syntax error: invalid arithmetic operator

That's it. In summary, Bash is typed and the types are integers, strings and lists.

EDIT: There are also arrays. That's topic for another post.

Ask us Anything. We'll get back to you shortly

linuxenglish
Start Demo Contact Us

Latest Blog Posts

Using object tracking to combat flickering detections in videos

How to decrease the amount of flickering detections in videos with object tracking.


How to copy XMP metadata between JPEG images (again)

Copying XMP metadata between images isn't straightforward. Read how it's done correctly.


20x Faster Than NumPy: Mean & Std for uint8 Arrays

How to calculate mean and standard deviation 20 times faster than NumPy for uint8 arrays.