LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 04-14-2017, 09:37 PM   #1
luofeiyu
Member
 
Registered: Aug 2015
Posts: 237

Rep: Reputation: Disabled
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.
 
Old 04-14-2017, 11:23 PM   #2
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,852
Blog Entries: 1

Rep: Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868
Homework question?
 
Old 04-15-2017, 01:46 AM   #3
ondoho
LQ Addict
 
Registered: Dec 2013
Posts: 19,872
Blog Entries: 12

Rep: Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053Reputation: 6053
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.
 
2 members found this post helpful.
Old 04-15-2017, 02:18 AM   #4
NevemTeve
Senior Member
 
Registered: Oct 2011
Location: Budapest
Distribution: Debian/GNU/Linux, AIX
Posts: 4,852
Blog Entries: 1

Rep: Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868Reputation: 1868
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'
 
1 members found this post helpful.
Old 04-15-2017, 03:07 AM   #5
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,692

Rep: Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274
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.
 
2 members found this post helpful.
Old 04-15-2017, 03:11 PM   #6
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,653

Rep: Reputation: 255Reputation: 255Reputation: 255
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.
 
Old 04-16-2017, 02:50 AM   #7
astrogeek
Moderator
 
Registered: Oct 2008
Distribution: Slackware [64]-X.{0|1|2|37|-current} ::12<=X<=15, FreeBSD_12{.0|.1}
Posts: 6,258
Blog Entries: 24

Rep: Reputation: 4193Reputation: 4193Reputation: 4193Reputation: 4193Reputation: 4193Reputation: 4193Reputation: 4193Reputation: 4193Reputation: 4193Reputation: 4193Reputation: 4193
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!

Last edited by astrogeek; 04-16-2017 at 02:54 AM. Reason: Clarity
 
3 members found this post helpful.
Old 04-16-2017, 03:30 AM   #8
pan64
LQ Addict
 
Registered: Mar 2012
Location: Hungary
Distribution: debian/ubuntu/suse ...
Posts: 21,692

Rep: Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274Reputation: 7274
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.
 
2 members found this post helpful.
Old 04-16-2017, 04:15 AM   #9
Xeratul
Senior Member
 
Registered: Jun 2006
Location: UNIX
Distribution: FreeBSD
Posts: 2,653

Rep: Reputation: 255Reputation: 255Reputation: 255
Quote:
Originally Posted by astrogeek View Post
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.
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
[SOLVED] i/o format with printf in bash-shell RudraB Programming 3 08-13-2013 09:00 AM
[SOLVED] Sorting find result by date without printf nadigo Programming 8 04-26-2012 02:44 PM
printf format does not work ! casualzone Programming 3 01-04-2012 02:31 AM
What is type size_t's format in printf? duyuyang Linux - Newbie 7 07-20-2011 01:04 AM
Is there a currency format with printf() ? LUB997 Programming 1 01-03-2005 08:33 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:17 AM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration