Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Understanding escapes in echo

9 views
Skip to first unread message

Foo

unread,
Feb 8, 2012, 10:20:39 AM2/8/12
to
Hi,

Can anyone help me to understand the following behavior of echo?

bash-4.2$ echo \\n
\n
bash-4.2$ echo \\\n
\n
bash-4.2$ echo `echo \\\n`
\n
bash-4.2$ echo `echo \\n`
n

Laurianne Gardeux

unread,
Feb 8, 2012, 12:00:48 PM2/8/12
to
Foo:
Not an explication, but a variation more:

bash-4.2$ echo $(echo \\n)
\n

Dave Gibson

unread,
Feb 9, 2012, 1:35:46 PM2/9/12
to
It's the shell (and the subshell in the latter two examples). Some of
the backslashes are being processed as quoting the next character. The
remainder are being treated literally by echo.

Ed Morton

unread,
Feb 9, 2012, 2:58:37 PM2/9/12
to
Maybe but in reality you'd never use echo that way so it's not worth
thinking about. Let's see how this looks if you quote your expressions:

$ echo "\\n"
\n
$ echo "\\\n"
\\n
$ echo "$(echo "\\\n")"
\\n
$ echo "$(echo "\\n")"
\n

and if you follow the advice that's regularly given here and stop using
echo in favor of printf:

$ printf "%s\n" "\\n"
\n
$ printf "%s\n" "\\\n"
\\n
$ printf "%s\n" "$(printf "%s\n" "\\\n")"
\\n
$ printf "%s\n" "$(printf "%s\n" "\\n")"
\n

Looks to me like "\\" is simply an escaped backslash in the literal string
passed to printf while \n is a backslash then the letter n.

Interestingly, this is the first time I've actually come across a
difference between using `...` and $(...):

$ printf "%s\n" `printf "%s\n" "\\\n"`
\n
$ printf "%s\n" $(printf "%s\n" "\\\n")
\\n

Regards,

Ed.

Posted using www.webuse.net

Foo

unread,
Feb 9, 2012, 11:36:40 PM2/9/12
to
I am wondering why case 1 and case 2 give the same output but when
they are put into subshell the output is different?

Foo

unread,
Feb 9, 2012, 11:44:40 PM2/9/12
to
On Thu, 09 Feb 2012 at 19:58 GMT, Ed Morton <morto...@gmail.com> wrote:
> Foo <no-suc...@gmail.com> wrote:
>
>> Hi,
>>
>> Can anyone help me to understand the following behavior of echo?
>>
>> bash-4.2$ echo \\n
>> \n
>> bash-4.2$ echo \\\n
>> \n
>> bash-4.2$ echo `echo \\\n`
>> \n
>> bash-4.2$ echo `echo \\n`
>> n
>
> Maybe but in reality you'd never use echo that way so it's not worth
> thinking about. Let's see how this looks if you quote your expressions:
>

Yes, it is artificial.

> $ echo "\\n"
> \n
> $ echo "\\\n"
> \\n
> $ echo "$(echo "\\\n")"
> \\n
> $ echo "$(echo "\\n")"
> \n
>
> and if you follow the advice that's regularly given here and stop using
> echo in favor of printf:
>
> $ printf "%s\n" "\\n"
> \n
> $ printf "%s\n" "\\\n"
> \\n
> $ printf "%s\n" "$(printf "%s\n" "\\\n")"
> \\n
> $ printf "%s\n" "$(printf "%s\n" "\\n")"
> \n
>
> Looks to me like "\\" is simply an escaped backslash in the literal string
> passed to printf while \n is a backslash then the letter n.
>

Yeah, I am wondering why the last part "\n" is not treated as newline...


> Interestingly, this is the first time I've actually come across a
> difference between using `...` and $(...):
>
> $ printf "%s\n" `printf "%s\n" "\\\n"`
> \n
> $ printf "%s\n" $(printf "%s\n" "\\\n")
> \\n
>

Me too!!

Could anyone here give an explanation?

Thanks!

Dave Gibson

unread,
Feb 10, 2012, 7:02:03 AM2/10/12
to
Unquoted backslashes remove special meaning from the following
character (with an exception for a backslash+newline pair).

In the first example the first backslash quotes the second.

echo \\n
\\ -> \
n -> n
echo \n <- final command

In the second example the first backslash quotes the second and the
third backslash quotes the 'n'

echo \\\n
\\ -> \
\n -> n
echo \n <- final command

> but when
> they are put into subshell the output is different?

In the third and fourth examples the backslashes are being processed
twice -- once by the parent shell (outside the `...`) and again by the
subshell (inside the `...`).

When processing a back-quoted command substitution the parent shell
will only treat a backslash as escaping the next character if the next
character is a back-quote, a backslash or a dollar sign. If the
command substitution is within double quotes a backslash also escapes
a double quote.

In the third example the parent shell treats the first backslash as
quoting the second. As the third backslash is not followed by one
of [`\$] it is treated as a literal character. The subshell then
processes the command within back-quotes using unquoted backslash
rules.

echo `echo \\\n`
\\ -> \ }
\ -> \ } parent processing
n -> n }
echo \\n <- subshell command
\\ -> \ } subshell processing
n -> n }
echo \n <- command executed by subshell
\n <- captured output
echo \n <- final command

In the fourth example the parent shell treats the first backslash as
escaping the second. The subshell then processes the backslashes and
treats the '\' as escaping the 'n'.

echo `echo \\n`
\\ -> \ } parent processing
n -> n }
echo \n <- subshell command
\n -> n } subshell processing
echo n <- command executed by subshell
n <- captured output
echo n <- final command

You may be expecting your shell's echo to behave like echo -e.

Ed Morton

unread,
Feb 10, 2012, 7:31:50 AM2/10/12
to
printf: Because it's in the string to be printed, not in the format string.

echo: because your particular echo doesn't interpret escape sequences by
default. Try it with "-e":

$ echo "a\nb"
a\nb
$ echo -e "a\nb"
a
b

That inconsistency between echos is one reason people advise using printf.

Ed.

bsh

unread,
Feb 14, 2012, 5:56:52 PM2/14/12
to
I just recently posted a response that is pertainent to this issue,
ostensively dealing with options parsing, but with a script example
and addendum that expands upon your issue:

http://groups.google.com/group/comp.unix.shell/browse_thread/thread/c75c2537dbf1a093/a56dda51dc95ec90

As for "shell quoting", the only thing that you have to know now, is
that shell, quote parsing, and "word separation" really are internally
consistent, and when (with more scripting experience) you understand
how the shell (an interpreter) differs in the parsing of its code from
a
compiler's usual approach, it will eventually become understandable to
you. In the meantime, some documents to help you on your way are:

"UNIX SHELL Quote Tutorial"
http://www.grymoire.com/Unix/Quote.html

"Consultix Shell Quoting Guidelines"
http://www.consultix-inc.com/quoting1_2.txt

"A Guide to Unix Shell Quoting"
http://www.mpi-inf.mpg.de/~uwe/lehre/unixffb/quoting-guide.html

"The Open Group Base Specifications (IEEE Std 1003.1) -- 2.6 Word
Expansions"
http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_06

Read the above in the order they are listed. Good luck!

=Brian

Foo

unread,
Feb 15, 2012, 7:43:05 AM2/15/12
to
Excellent answer! This is exactly what I want!

Thanks, Dave!

Ivan Shmakov

unread,
Feb 16, 2012, 12:03:46 PM2/16/12
to
>>>>> Dave Gibson <dave.gma> writes:
>>>>> Foo <no-suc...@gmail.com> wrote:
>>>>> On Thu, 09 Feb 2012 at 18:35 GMT, Dave Gibson wrote:
>>>>> Foo <no-suc...@gmail.com> wrote:

[...]

>>>> bash-4.2$ echo `echo \\\n`
>>>> \n
>>>> bash-4.2$ echo `echo \\n`
>>>> n

>>> It's the shell (and the subshell in the latter two examples). Some
>>> of the backslashes are being processed as quoting the next
>>> character. The remainder are being treated literally by echo.

[...]

>> but when they are put into subshell the output is different?

> In the third and fourth examples the backslashes are being processed
> twice -- once by the parent shell (outside the `...`) and again by
> the subshell (inside the `...`).

... And that's why they prefer $() over `` nowadays. Consider,
e. g.:

$ echo $(echo \\\n)
\n
$ echo $(echo \\n)
\n
$

These also nest neatly, like:

$ echo $(echo $(echo $(echo $(echo $(echo $(echo \\n))))))
\n
$

[...]

--
FSF associate member #7257

bsh

unread,
Feb 16, 2012, 7:57:30 PM2/16/12
to
bsh <brian_hi...@rocketmail.com> wrote:
> Foo <no-such-u...@gmail.com> wrote:
> > ...
> ...

In addition to the links already provided, let me add another one just
discovered and appreciated of Sven Mascheck's great resource
regarding shell versions, portability concerns, and their host OSes,
in regard to my most recent posting:

"echo(1) And printf(1)"
http://www.in-ulm.de/~mascheck/various/echo+printf/

=Brian

0 new messages