bug#20553: 'echo -e' does not escape backslash correctly

2015-05-12 Thread Erik Auerswald
Hi,

On Mon, May 11, 2015 at 11:17:34PM +0100, Stephane Chazelas wrote:
 2015-05-11 23:50:25 +0200, Jo Drexl (FFGR-IT):
  Hi guys,
  I had to write a Windows bat file for twentysomething users and - as
  Linux geek - wrote a small Bash script for it. The code in question is
  as follows:
  
  echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME%
  $BG_PASSWD\r
 [...]
 
 If that's a bash script, then that has nothing to do with GNU
 coreutils as bash has its own builtin version of echo.
 
 In any case, there's no bug here. and GNU coreutils echo or the
 bash one behave the same.
 
 \ is used as an escape character both for the bash language
 within double quotes, and for echo -e.
 
 echo -e 
 
 Passes 3 arguments to echo: echo, -e and \\

So you need to add another handful of \ characters:

$ echo -e 
\\
$ /bin/echo -e 
\\

Erik





bug#20553: 'echo -e' does not escape backslash correctly

2015-05-12 Thread Stephane Chazelas
2015-05-11 17:36:50 -0600, Eric Blake:
 On 05/11/2015 04:14 PM, Pádraig Brady wrote:
 
  echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% 
  $BG_PASSWD\r
 
 'echo -e' is non-portable.  POSIX recommends that you use printf
 instead, as the POSIX version of echo is supposed to behave as follows:
 
 $ echo -e 'a\nb'
 -e a\nb
[...]

Strictly speaking without XSI (Unix conformance), the behaviour
of that command is unspecified because the arguments contain
backslash.

With XSI, the behaviour is specified but the expected output is:

-e anewlinebnewline

 You are relying on non-POSIX behavior for backslash interpolation.
 
  Note echo is not portable to other systems, and if that's required,
 
 In fact, it's not even portable to bash:
 
 $ shopt -s xpg_echo
 
 tells bash to turn on POSIX rules for echo, invalidating any bash script
 that relies on 'echo -e'.

xpg_echo alone doesn't make bash's echo POSIX compliant. It just means
-e is implicit. It wouln't break scripts that use echo -e,
just script that use echo without -e and expect escape
sequences not to be expanded.

To have a Unix (POSIX+XSI) conformant echo, you need both the
posix (set -o posix) and xpg_echo (shopt -s xpg_echo) options.

Those can also be enabled via the environment (BASHOPTS,
SHELLOPTS, POSIXLY_CORRECT) or at compile time. bash will also
enable posix when called as sh.

See
https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo
for more info.

 
  printf(1) is a better option, though that will have different
  quoting again due to the % chars etc.
 
 % doesn't need quoting in shell.  But yes, printf is more portable.

% needs escaped (with %) in the format argument though, which is
probaby what Pádraig was refering to.

-- 
Stephane






bug#20553: 'echo -e' does not escape backslash correctly

2015-05-11 Thread Pádraig Brady
tag 20553 notabug
close 20553
stop

On 11/05/15 22:50, Jo Drexl (FFGR-IT) wrote:
 Hi guys,
 I had to write a Windows bat file for twentysomething users and - as Linux 
 geek - wrote a small Bash script for it. The code in question is as follows:
 
 echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r
 
 I expected the created files being as such:
 net use z: \\srv\aqs /persistent:no /user:%USERNAME% user-password
 
 but got:
 net use z: \srvqs /persistent:no /user:%USERNAME% user-password
 
 Without the parameter e the code for a working file had to be:
 echo net use z: \\srv\aqs /persistent:no /user:%USERNAME% $BG_PASSWD
 but missed the Windows-newline carriage return (\r) - adding that without 
 changing the echo command didn't print out the carriage return character but 
 the literal backslash-R, as the default behaviour (parameter E) indicates.
 
 Long story short: Escaping doesn't work correctly, either it's the Bash 
 interfering (but only escaping the double backslashes, and afterwards echo -e 
 escaping everything correctly), or the double backslash escape doesn't work 
 at all. It CAN be healed by using single quotes, but then variable expansion 
 doesn't work, or by using a variable workaround:
 
 BG_SHARE='srv\\aqs'
 echo -e net use z: $BG_SHARE /persistent:no /user:%USERNAME% $BG_PASSWD\r
 
 but I'm pretty positive this is a workaround, not the way it should work.
 
 Maybe you dig into it, if you have the time. Since I found nothing worthy 
 googleing the issue, it seems like a quite uncommon situation I'm in.
 
 BR
 Jo
 
 P.S.: It's a standard Debian Wheezy without clickery GUI. No funny changes to 
 the default behaviour of Bash or the login shell.


The shell _and_ echo -e are processing the \'s
To get the shell to stop you can use single quotes like:

 echo -e 'net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r'

Or to leave to shell to also process \r you can:

 echo $'net use z: srv\\aqs /persistent:no /user:%USERNAME% $BG_PASSWD\r'

Note echo is not portable to other systems, and if that's required,
printf(1) is a better option, though that will have different
quoting again due to the % chars etc.

cheers,
Pádraig.





bug#20553: 'echo -e' does not escape backslash correctly

2015-05-11 Thread Jo Drexl (FFGR-IT)
Hi guys,
I had to write a Windows bat file for twentysomething users and - as
Linux geek - wrote a small Bash script for it. The code in question is
as follows:

echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME%
$BG_PASSWD\r

I expected the created files being as such:
net use z: \\srv\aqs /persistent:no /user:%USERNAME% user-password

but got:
net use z: \srvqs /persistent:no /user:%USERNAME% user-password

Without the parameter e the code for a working file had to be:
echo net use z: \\srv\aqs /persistent:no /user:%USERNAME% $BG_PASSWD
but missed the Windows-newline carriage return (\r) - adding that
without changing the echo command didn't print out the carriage return
character but the literal backslash-R, as the default behaviour
(parameter E) indicates.

Long story short: Escaping doesn't work correctly, either it's the Bash
interfering (but only escaping the double backslashes, and afterwards
echo -e escaping everything correctly), or the double backslash escape
doesn't work at all. It CAN be healed by using single quotes, but then
variable expansion doesn't work, or by using a variable workaround:

BG_SHARE='srv\\aqs'
echo -e net use z: $BG_SHARE /persistent:no /user:%USERNAME% $BG_PASSWD
\r

but I'm pretty positive this is a workaround, not the way it should
work. 

Maybe you dig into it, if you have the time. Since I found nothing
worthy googleing the issue, it seems like a quite uncommon situation I'm
in.

BR
Jo

P.S.: It's a standard Debian Wheezy without clickery GUI. No funny
changes to the default behaviour of Bash or the login shell.


signature.asc
Description: This is a digitally signed message part


bug#20553: 'echo -e' does not escape backslash correctly

2015-05-11 Thread Eric Blake
On 05/11/2015 04:14 PM, Pádraig Brady wrote:

 echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME% 
 $BG_PASSWD\r

'echo -e' is non-portable.  POSIX recommends that you use printf
instead, as the POSIX version of echo is supposed to behave as follows:

$ echo -e 'a\nb'
-e a\nb

You are relying on non-POSIX behavior for backslash interpolation.

 Note echo is not portable to other systems, and if that's required,

In fact, it's not even portable to bash:

$ shopt -s xpg_echo

tells bash to turn on POSIX rules for echo, invalidating any bash script
that relies on 'echo -e'.

 printf(1) is a better option, though that will have different
 quoting again due to the % chars etc.

% doesn't need quoting in shell.  But yes, printf is more portable.

-- 
Eric Blake   eblake redhat com+1-919-301-3266
Libvirt virtualization library http://libvirt.org



signature.asc
Description: OpenPGP digital signature


bug#20553: 'echo -e' does not escape backslash correctly

2015-05-11 Thread Stephane Chazelas
2015-05-11 23:50:25 +0200, Jo Drexl (FFGR-IT):
 Hi guys,
 I had to write a Windows bat file for twentysomething users and - as
 Linux geek - wrote a small Bash script for it. The code in question is
 as follows:
 
 echo -e net use z: srv\\aqs /persistent:no /user:%USERNAME%
 $BG_PASSWD\r
[...]

If that's a bash script, then that has nothing to do with GNU
coreutils as bash has its own builtin version of echo.

In any case, there's no bug here. and GNU coreutils echo or the
bash one behave the same.

\ is used as an escape character both for the bash language
within double quotes, and for echo -e.

echo -e 

Passes 3 arguments to echo: echo, -e and \\

Same as

echo -e '\\'

And echo then treats \\ as an escaped \.

You've got another problem in that escape sequences are expanded
in your variables.

Here, you want:

printf '%s\r\n' net use z: srv\\aqs /persistent:no /user:%USERNAME% 
$BG_PASSWD

or:

printf '%s\r\n' 'net use z: \\srv\aqs /persistent:no /user:%USERNAME% 
'$BG_PASSWD

or:

printf 'net use z: srv\\aqs /persistent:no /user:%%USERNAME%% %s\r\n' 
$BG_PASSWD

etc...

-- 
Stephane