Quotation marks and escaping

Bash has only one data type, which is string. No matter what data the user enters, Bash treats it as a string. Therefore, quotation marks and escaping related to strings are very important to Bash.

Escaping

Certain characters have special meanings in Bash (such as $, &, *).

$ echo $date

$

In the above example, the output of $date will not produce any results, because $ is a special character.

If you want to output these special characters as they are, you must add a backslash in front of them to make them normal characters. This is called "escape" (escape).

$ echo \$date
$date

In the above command, only by adding a backslash in front of the special character $, it can be output as it is.

The backslash itself is also a special character. If you want to output the backslash as it is, you need to escape it and use two backslashes (\\) in succession.

$ echo \\
\

The above example outputs the backslash itself.

In addition to being used for escaping, backslashes can also represent some non-printable characters.

-\a: bell -\b: backspace -\n: line break -\r: carriage return -\t: Tab character

If you want to use these non-printable characters on the command line, you can put them in quotes, and then use the -e parameter of the echo command.

$ echo a\tb
atb

$ echo -e "a\tb"
ab

In the above example, the command line directly outputs the non-printable character \t, which Bash cannot interpret correctly. You must put them in quotation marks, and then use the -e parameter of the echo command.

The newline character is a special character that indicates the end of the command. After receiving this character, Bash will interpret and execute the input command. Adding a backslash escape before the newline character makes the newline character a normal character, and Bash treats it as a space, so that one line of commands can be written into multiple lines.

$ mv \
/path/to/foo \
/path/to/bar

# Equivalent to
$ mv /path/to/foo /path/to/bar

In the above example, if a command is too long, you can use a backslash at the end of the line to rewrite it into multiple lines. This is a common way of writing multi-line commands.

apostrophe

Bash allows strings to be quoted in single or double quotes.

Single quotation marks are used to preserve the literal meaning of characters. Various special characters will become ordinary characters in single quotation marks, such as asterisk (*), dollar sign ($), backslash (\) Wait.

$ echo'*'
*

$ echo'$USER'
$USER

$ echo'$((2+2))'
$((2+2))

$ echo'$(echo foo)'
$(echo foo)

In the above command, single quotes make Bash extensions, variable references, arithmetic operations and subcommands invalid. If you don't use single quotes, they will all be automatically expanded by Bash.

Since the backslash becomes an ordinary character in the single quotation mark, if the single quotation mark is also used, the single quotation mark must be used instead of escaping. You need to add a dollar sign ($) in front of the outer single quotation mark. Then escape the inner single quote.

# Incorrect
$ echo it's

# Incorrect
$ echo'it\'s'

# Correct
$ echo $'it\'s'

However, a more reasonable way is to use single quotation marks in double quotation marks instead.

$ echo "it's"
it's

Double quotes

Double quotation marks are looser than single quotation marks. Most special characters in double quotation marks lose their special meaning and become ordinary characters.

$ echo "*"
*

In the above example, the wildcard character * is a special character, put in double quotes, it becomes a normal character, and it will be output as it is. This requires special attention, which means that no file name expansion will be performed inside the double quotes.

However, three special characters are excluded: dollar sign ($), backquote (`` ```), and backslash (\). These three characters in double quotes still have special meanings and will be automatically expanded by Bash.

$ echo "$SHELL"
/bin/bash

$ echo "`date`"
Mon Jan 27 13:33:18 CST 2020

In the above example, the dollar sign ($) and the backquote (`` ```) in the double quotation marks retain their special meaning. The dollar sign is used to quote variables, and the backtick is to execute subcommands.

$ echo "I'd say: \"hello!\""
I'd say: "hello!"

$ echo "\\"
\

In the above example, the backslash has a special meaning in the double quotation marks and is used for escaping. Therefore, you can use backslashes, insert double quotes between double quotes, or insert the backslash itself.

The newline character in double quotation marks loses its special meaning, and Bash no longer interprets it as the end of the command, just as a normal newline character. So you can use double quotes to enter multiple lines of text on the command line.

$ echo "hello
world"
hello
world

In the above command, Bash will normally interpret the newline character as the end of the command, but the newline character in the double quotation marks loses its special function and is only used for line breaks, so you can enter multiple lines. The echo command will output the newline character as it is, and interpret it as a newline when displayed.

Another common use of double quotation marks is when file names contain spaces. At this time, you must use double quotation marks and put the file name inside.

$ ls "two words.txt"

In the above command, two words.txt is a file name containing spaces, otherwise it will be treated as two files by Bash.

Double quotes will save the extra spaces as they are.

$ echo "this is a test"
this is a test

Double quotation marks have another effect, which is to save the output format of the original command.

# Single line output
$ echo $(cal)
January 2020 One Two Three Four Five Six 1 2 3 ... 31

# Original format output
$ echo "$(cal)"
      January 2020
Day one two three four five six
          1 2 3 4
 5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31

In the above example, if $(cal) is not enclosed in double quotes, echo will output all results in a single line, discarding all original formats.

Here document

Here document (here document) is a way to enter a multi-line string, the format is as follows.

<< token
text
token

Its format is divided into start token (<< token) and end token (token). The start tag is the name of the document with two less than signs + Here. The name can be taken at will, and must be followed by a newline character; the end tag is the name of the Here document written in the top grid on a single line. If it is not the top grid, the end tag will not work. Between the two is the content of the multi-line string.

The following is an example of outputting HTML code through Here document.

$ cat << _EOF_
<html>
<head>
    <title>
    The title of your page
    </title>
</head>

<body>
    Your page content goes here.
</body>
</html>
_EOF_

Variable substitution occurs inside the Here document, and backslash escaping is also supported, but wildcard expansion is not supported. Double quotation marks and single quotation marks also lose their grammatical effect and become ordinary characters.

$ foo='hello world'
$ cat << _example_
$foo
"$foo"
'$foo'
_example_

hello world
"hello world"
'hello world'

In the above example, the variable $foo has been replaced, but the double quotes and single quotes are output as they are, indicating that they have lost their quoting function.

If you don't want variable substitution to occur, you can put the opening tag of the Here document in single quotes.

$ foo='hello world'
$ cat <<'_example_'
$foo
"$foo"
'$foo'
_example_

$foo
"$foo"
'$foo'

In the above example, the opening tag (_example_) of the Here document is placed in single quotes, which makes the variable substitution invalid.

The essence of the Here document is redirection, which redirects the output of the string to a certain command, which is equivalent to including the echo command.

$ command << token
  string
token

# Equivalent to

$ echo string | command

In the above code, the Here document is equivalent to the redirection of the echo command.

Therefore, the Here string is only suitable for commands that can accept standard input as a parameter, and is invalid for other commands. For example, the echo command cannot use the Here document as a parameter.

$ echo << _example_
hello
_example_

The above example will not have any output, because the Here document is invalid for the echo command.

In addition, the Here document cannot be used as the value of a variable, and can only be used as a parameter of a command.

Here string

There is also a variant of the Here document, called Here string, which is represented by three less than signs (<<<).

<<< string

Its function is to pass the string to the command through standard input.

Some commands accept the given parameters directly, and accept the parameters through standard input, the result is not the same. This grammar makes it more convenient to pass strings to commands through standard input. For example, the cat command only accepts strings from standard input.

$ cat <<<'hi there'
# Equivalent to
$ echo'hi there' | cat

The first syntax above uses the Here string, which has better semantics and is more concise than the second syntax.

$ md5sum <<<'ddd'
# Equivalent to
$ echo'ddd' | md5sum

In the above example, the md5sum command can only accept standard input as a parameter. You cannot put a string directly after the command. It will be treated as a file name, that is, the ddd in md5sum ddd will be interpreted as a file name. At this time, you can use the Here string to pass the string to the md5sum command.