(One)-minute geek news

Group talks, Laboratoire de Chimie, ENS de Lyon

Quotings


Multiple quotings are available in Bash. Let us explore the specificities of them.

Introduction

Quoting mechanisms allow to escape metacharacters and expressions that would be interpreted. More precisely, in Bash, quotings are part of escaping mechanisms to prevent the interpretation of metacharacters and/or expansions and/or substitutions.

In other words, Bash perform A LOT of command preprocessing (this is a tricky yet powerful specificity of Bash), depending on the context. Quotings are setting such context, basically disabling/enabling some preprocessing mechanisms.

Since multiple expansions/substitutions are available in Bash (see previous bash trick for example), multiple quotings and escape mechanisms exist to escape specific expansions/substitutions.

Let us review the most common escaping mechanisms and their associated interpretable expressions.

Command preprocessing mechanisms

They are far too many metacharacters and expressions that can be interpreted in Bash for me to quickly list them here (that would be rewriting half of the Bash manual). So let us review the most relevant in this case (in my opinion):

Metacharacters

| & ; ( ) < > space tab

Those metacharacters are interpreted by Bash, and separate words (or token).

Control operators

|| & && ; ;; ( ) | |& <newline>

Those are the token that perfom a control function (basically chain commands together).

Escaping characters

' " \

The escaping characters themselves

Reserved words

! case coproc do done elif else esac fi for function if in select then until while { } time [[ ]]

Those words are recognized as reserved if unquoted and either the first word of a simple command, or the third word of a case or for command.

$ based expansions/substitutions

Parameter expansion

Basically using variables in Bash (which is unconventional compared to other languages).

Example: MY_VAR=42 ; echo $MY_VAR. The first command will assign 42 to MY_VAR. In the second command, Bash will replace $MY_VAR by the assigned value of MY_VAR.

Parameter expansions are far more complex and powerful, but I won't describe them here.

Arithmetic expansion

Basic calculus with Bash.

Example: echo $((4*13)) will display 42.

Notes: The old format $[expression] is deprecated and will be removed in upcoming versions of bash.

Command substitution

Command substitution allows the output of a command to replace the command name.

Two forms are possible: $(command) or the old-style `command`

Example: DATE_START=$(date) or E_ref=$(awk '/C2H2/ {print $11}' energy_profiles|sort -n|tail -1).

Note: I prefer the $(command) form for at least three reasons:

  • Readability.
  • Command substitutions can be nested: $(grep $(date +%F) my_file|sort|tail -1).
  • Contexts subtilities leading to this: a=3;echo \$a $(a=3;echo \$a) `a=3;echo \$a` giving $a $a 3.

History expansions

Class of substitutions that replace from bash history.

They start with !, and I won't go into details. Example: !! is replaced by the previous command.

Aliases

You probably know now how they work.

Example: alias cd=pushd will now replace all your cd commands by pushd commands.

Quoting contexts

The bash manual counts 5 quoting mechanisms ("", '', \, $'', $""), and I count at least 15 different contexts in Bash. Therefore, I will only focus on the main 3 quotings contexts: backslash escaping ; single quotes and double quotes.

Backslash escaping

How to use: A non-quoted backslash (\) is the escape character. It preserves the literal value of (i.e. escape) the next character that follows.

Exceptions: If a backslash escaped newline appears (\<newline>), it is treated as a line continuation (that is, it is removed from the input stream and effectively ignored).

Advanced: \command refers to the unaliased command (if used as first word of a simple command).

Single quotes

How to use: 'expression'

This is most simple quoting context: absolutely no expansion/substitutions are performed on expression.

In other words (as the manual states it), enclosing characters in single quotes preserves the literal value of each character within the quotes.

Notes: As a consequence, a single quote (') cannot be part of expression (because it can't be escaped, since the escaping characters have they litteral values!)...

Double quotes

How to use: "expression"

All expansion/substitutions are disabled, expect for $-based expansions, command substitutions, backslash escapings and history expansions.

In other words (as the manual states it), enclosing characters in double quotes preserves the literal value of all characters within the quotes, with the exception of $, `, \, and !

Exceptions (otherwise it would not be fun): double quoted backslashes only escape the following characters: $, \, `, and ". Otherwise they retain their litteral value.

Advanced: History expansion is disabled in double quotes only if the shell is in posix mode, or history expansion is disabled...

Advanced: The special parameters * and @ have special meaning when in double quotes... (see man bash)

References

man bash