3

I just started learning Bash so I apologize for the following questions that may seem overly elementary.

I struggling to understand the use of quotes in Shell Scripts.

If I were to write

a="file"
b="`grep " a" "$a"`"
echo $b
  1. Should they be read as "$a" and " a" within the quote "`grep " a" "$a"`"?

    or, it is read from left to right?

    Since I was taught to enclose variables with double-quotes.

    And to add to the confusion, my teacher told me that in order to prevent the system from misinterpreting the variable name with the text that coes after it, we should add another double quote around the variable name.

  2. What do nested quotes do? And when should we use quotes?

2 Answers2

4

Normal quotes don't nest, but backquotes are special in double quotes.

It's more readable and cleaner to use $() instead of backquotes. They both mean the command substitution, i.e. they expand to the output of the command they enclose.

b="$(grep " a" "$a")"

But you don't need the outer double quotes in an assignment, so the following is equivalent:

b=$(grep " a" "$a")

Your question has changed, so let's add some more details: You should use double quotes everywhere where you want to prevent word splitting. The issue with variable names is best demonstrated in

echo "$var1_$var2"    # two variables, $var1_ and $var2
echo "$var1"_"$var2"  # two variables, $var1 and $var2, separated by an underscore
# also possible:
echo "${var1}_$var2"
choroba
  • 47,233
1

Since you used the archaic form of command substitution with backticks, the answer is "it depends". Some shells (e.g. Bash) have the backticks start a new quoting context, so inner pairs of double quotes nest inside the backticks and the outer double quotes, and you end up with these four quoted parts:

b="`grep " a" "$a"`"
#        c--c d--d
#  b--------------b
# a----------------a

But... Some other shells (ksh) parse that so that the second double-quote ends the double-quoted string regardless of the backtick in the middle. The result is something like this:

b="`grep " a" "$a"`"
# a------a  b-b  c-c

Which doesn't do what you want. (It runs grep '', assigns the output of that to b, then runs a , with an argument given by an empty command substitution.)

See: quotes inside backticks inside quotes in ksh

Unsurprisingly, POSIX leaves that case undefined.


That said, if you were to change to using the $(...) form of command substitution, you'd avoid that situation, and in there, the expansion always starts a new quoting context, so it nests within the double-quotes, and the double-quotes inside nest within the $(...).

b="$(grep " a" "$a")"
#         c--c d--d
#   b--------------b
# a-----------------a

See:

And remember, friends don't let friends use backticks.


And to add to the confusion, my teacher told me that in order to prevent the system from misinterpreting the variable name with the text that coes after it, we should add another double quote around the variable name.

For this, you can use quotes, or put braces around the variable name. So, below $foo is expanded and the fixed string bar appended, in all three variants:

$ foo=xxx
$ echo "$foo""bar" "$foo"bar "${foo}bar" 
xxxbar xxxbar xxxbar

That last one is probably easiest to read.

What do nested quotes do? And when should we use quotes?

Quotes don't nest with each other without something like a command substitution in between, as above. Without one, similar quotes just end the quoting, and other quotes just act like normal characters, without quoting anything.

E.g. this is two quoted strings with an unquoted part in between:

  "foo "abc def" bar"
# <---->       <---->
#          ^ unquoted space.

And here is one quoted string that just so happens to contain single quote characters:

$ echo "foo 'abc def' bar"
foo 'abc def' bar

The single quotes get passed to echo as part of the command-line argument, just like the letters and spaces. They don't quote anything.

As for when, see: When is double-quoting necessary?

ilkkachu
  • 138,973