LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Programming (https://www.linuxquestions.org/questions/programming-9/)
-   -   why \\\\ and \\\\\ in printf format result in same output? (https://www.linuxquestions.org/questions/programming-9/why-%5C%5C%5C%5C-and-%5C%5C%5C%5C%5C-in-printf-format-result-in-same-output-4175603867/)

luofeiyu 04-14-2017 09:37 PM

why \\\\ and \\\\\ in printf format result in same output?
 
Code:

debian8@debian:~$ printf  %-5s\\\\n  "hah"
hah  \ndebian8@debian:~$
debian8@debian:~$ printf  %-5s\\\\\n  "hah"
hah  \ndebian8@debian:~$

All of them print \n literally without newline,why?
Please explain it in detail.

NevemTeve 04-14-2017 11:23 PM

Homework question?

ondoho 04-15-2017 01:46 AM

i don't think so.
this user has a different posting history.
and i have been asking myself the same / a similar question sometimes, but with php.
in my shell bash i get very different behavior:
Code:

$> printf '\\\n'
\
$> printf '\\\\n'
\\n$> printf '\\\\\n'
\\
$> printf '\\\\\\n'
\\\n$>

etc.

NevemTeve 04-15-2017 02:18 AM

Well, 'quotes' do "matter". It isn't hard to test the possible combinations:
Code:

echo a\\b
echo 'a\\b'
echo "a\\b"
echo $'a\\b'


pan64 04-15-2017 03:07 AM

ok, let's have a try: what will happen when you press enter? First the current bash will try to evaluate the command line you entered.
Code:

printf        is a (built-in) command, which will be executed
<white space> separator among arguments
%-5s          is taken as-is, bash will not do anything with it
\\            is a protected \, so bash will evaluate it as \
\\            again, will be replaced by a single \
n            is a letter n, will stay as-is
<white space> separator among arguments
"hah"        protected string, will be evaluated as: hah
#----
#finally this will be executed:
printf %-5s\\n hah
# which will be:
  hah\n
# because \\ will be printed as \ and %-5s means left justified "hah  ", but I think you know it.

let's see the second command:
Code:

printf        is a (built-in) command, which will be executed
<white space> separator among arguments
%-5s          is taken as-is, bash will not do anything with it
\\            is a protected \, so bash will evaluate it as \
\\            again, will be replaced by a single \
\n            is a protected letter n, will stay as a single n
<white space> separator among arguments
"hah"        protected string, will be evaluated as: hah
#----
#finally this will be executed:
printf %-5s\\n hah
# which is exactly the same as before

finally check: printf '%-5s\\\\\n' "hah"
Code:

printf
<white space>
'%-5s\\\\n'    protected string, passed as-is
<white space>
"hah"          -> hah
# so this will be executed as-is, without command line evaluation
# printf will now work on 5 \ chars, (two protected \) and the last one + n will be interpreted as a new line, so
hah  \\  <and a new line

# will be printed.


Xeratul 04-15-2017 03:11 PM

I would recommend to start to read about the original C language, first. Then, you can see why \\ or why \n. There is something important with '\', i.e. how your linux and windows 7,8,10 works.

astrogeek 04-16-2017 02:50 AM

Different languages and contexts have different escape characters and sequences. The '\' has special meaning in C, PHP, the shell and a good many other languages, although the rules are not always the same (as we will see below!). The question in this thread is specifically about the shell, and about printf in shell context which adds its own rules for '\'.

I usually think that people who seek out edge cases and obscure command superpositions really have too much time on their hands! ;)

There are also differences in printf usage among shells, so we will restrict what follows to Bash which uses a built-in printf.

The obscurity of the case posted here is caused by the fact that the backslashes are handled twice, with different rules!

First, because the format string is not quoted, the shell applies its rules for special meaning of the backslash:
Code:

\\=\
\n=n

Then printf receives the resulting format string, and applies its own rules:

Code:

\\=\
\n=<newline>

As pan64 has shown, both the case of \\\\n and \\\\\n are reduce by the shell to \\n, which printf interprets as \ followed by the letter n, or literal \n.

As noted above, quoting is important, and I can hardly think of a useful case where you would not want to quote a printf format string! But there are still two choices... single quotes and double quotes. In this case the single quoted string is usually the winner, it protects the format string from shell interpretation and tells printf what you really mean!

Now, all that said, it is interesting to compare the different patterns that result from unquoted, single quoted and double quoted format strings. Following are examples of one through eight backslashes followed by 'n', in each case, using the OP's printf specifiers.

Unquoted format string - slashes escaped by shell, \\=\, \n=n:
Code:

      xxx=string, (nl)=newline                Printf sees:    Result:
printf  %-5s\n  "01" #                        %-5sn          xxx  n
printf  %-5s\\n  "02" #                        %-5s\n          xxx  (nl)
printf  %-5s\\\n  "03" #                      %-5s\n          xxx  (nl)
printf  %-5s\\\\n  "04" #                      %-5s\\n        xxx  n
printf  %-5s\\\\\n  "05" #                    %-5s\\n        xxx  n
printf  %-5s\\\\\\n  "06" #                    %-5s\\\n        xxx  \(nl)
printf  %-5s\\\\\\\n  "07" #                  %-5s\\\n        xxx  \(nl)
printf  %-5s\\\\\\\\n  "08" #                  %-5s\\\\n      xxx  \\n

Single quoted format string - no shell escape handling
Code:

      xxx=string, (nl)=newline                Printf sees:            Result:
printf  '%-5s\n'  "01" #                      %-5s\n                  xxx  (nl)
printf  '%-5s\\n'  "02" #                      %-5s\\n                xxx  \n
printf  '%-5s\\\n'  "03" #                    %-5s\\\n                xxx  \(nl)
printf  '%-5s\\\\n'  "04" #                    %-5s\\\\n              xxx  \\n
printf  '%-5s\\\\\n'  "05" #                  %-5s\\\\\n              xxx  \\(nl)
printf  '%-5s\\\\\\n'  "06" #                  %-5s\\\\\\n            xxx  \\\n
printf  '%-5s\\\\\\\n'  "07" #                %-5s\\\\\\\n            xxx  \\\(nl)
printf  '%-5s\\\\\\\\n'  "08" #                %-5s\\\\\\\\n          xxx  \\\\n


Double quoted format string - slashes escaped by quoting, \\=\, \n=\ followed by n
Code:

      xxx=string, (nl)=newline                Printf sees:            Result:
printf  "%-5s\n"  "01" #                      %-5s\n                  xxx  (nl)
printf  "%-5s\\n"  "02" #                      %-5s\n                  xxx  (nl)
printf  "%-5s\\\n"  "03" #                    %-5s\\n                xxx  \n
printf  "%-5s\\\\n"  "04" #                    %-5s\\n                xxx  \n
printf  "%-5s\\\\\n"  "05" #                  %-5s\\\n                xxx  \(nl)
printf  "%-5s\\\\\\n"  "06" #                  %-5s\\\n                xxx  \(nl)
printf  "%-5s\\\\\\\n"  "07" #                %-5s\\\\n              xxx  \\n
printf  "%-5s\\\\\\\\n"  "08" #                %-5s\\\\n              xxx  \\n

Note the different alternations in output that result from the different meaning of backslashes in each case, interacting with the printf rules. There are additional cases that can arise too, but I leave that as an exercise for the truly bored! ;)

The lesson to be learned: Always single quote printf format strings in shell scripts, and use the time you save for better purposes!

pan64 04-16-2017 03:30 AM

additionally you can use set -xv to see what's happening (for example):
Code:

user@host:~$ set -xv
user@host:~$ printf  "%-5s\\\\n"  "04"
printf  "%-5s\\\\n"  "04"
+ printf '%-5s\\n' 04
04  \nuser@host:~$

the purple line was entered and the blue line was really executed after evaluation, and orange is the result.

Xeratul 04-16-2017 04:15 AM

Quote:

Originally Posted by astrogeek (Post 5697554)
Different languages and contexts have different escape characters and sequences. The '\' has special meaning in C, PHP, the shell and a good many other languages, although the rules are not always the same (as we will see below!). The question in this thread is specifically about the shell, and about printf in shell context which adds its own rules for '\'.

PHP came much later.

It comes from earlier A and B languages.


All times are GMT -5. The time now is 10:40 AM.