Your shell is interpreting the quotes, both '
and "
, before they even get to echo
. I generally just put double quotes around my argument to echo even if they're unnecessary; for example:
$ echo "Hello world"
Hello world
So in your first example, if you want to include literal quote marks in your output, they either need to be escaped:
$ echo \'Hello world\'
'Hello world'
Or they need to be used within a quoted argument already (but it can't be the same kind of quote, or you'll need to escape it anyway):
$ echo "'Hello world'"
'Hello world'
$ echo '"Hello world"'
"Hello world"
In your second example, you're running a command substitution in the middle of the string:
grep $ARG /var/tmp/setfile | awk {print $2}
Things that start with $
are also handled specially by the shell -- it treats them as variables and replaces them with their values. Since most likely neither of those variables are set in your shell, it actually just runs
grep /var/tmp/setfile | awk {print}
Since grep
only sees one argument, it assumes that argument is the pattern you're searching for, and that the place it should read data from is stdin, so it blocks waiting for input. That's why your second command appears to just hang.
This won't happen if you single-quote the argument (which is why your first example nearly worked), so this is one way to get the output you want:
echo \'' echo PARAM=` grep $ARG /var/tmp/setfile | awk '{print $2}' ` '\'
You can also double-quote it, but then you'll need to escape the $
s so the shell doesn't resolve them as variables, and the backticks so the shell doesn't run the command substitution right away:
echo "' echo PARAM=\` grep \$ARG /var/tmp/setfile | awk '{print \$2}' \` '"
For the unquoted example, each \\
pair passes one backslash to grep, so 4 backslashes pass two to grep, which translates to a single backslash. 6 backslashes pass three to grep, translating to one backslash and one \c
, which is equal to c
. One additional backslash does not change anything, because it is translated \c
-> c
by the shell. Eight backslashes in the shell are four in grep, translated to two, so this does not match anymore.
For the example in double quotes, note what follows your second quote from the bash manpage:
The backslash retains its
special meaning only when followed by one of the following characters:
$, `, ", \, or newline.
I.e. when you give an odd number of backslashes, the sequence ends in \c
, which would be equal to c
in the unquoted case, but when quoted, the backslash looses its special meaning, so \c
is passed to grep. That is why the range of "possible" backslashes (i.e. those that make up a pattern matching your example file) slides down by one.
Best Answer
The tutorial is wrong.
POSIX says:
Here's some alternatives:
Further reading: Quotes - Greg's Wiki