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 Xia


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.

linuxenglish
Contact Us

Latest Blog Posts

Smart Cities and Mobile Mapping

Learn how the city of Vienna took advantage of Mobile Mapping to improve its Smarty City digital service for citizens and companies.


Data Protection for Mobile Mapping (for experts)

History and Implications of Data Protection Laws like GDPR, CCPA, etc. for Mobile Mapping.


Image Anonymization for Mobile Mapping

Achieving Legal Compliance of Mobile Mapping by Anonymizing Images.