3

The following sequence of commands

ch=`echo "b_d" | sed 's/_/\\\\\\\\_/'`
echo $ch

when executed in a terminal or via source give an output

b\\_d

When ran as a scipt

sh script.sh

where the script contents are:

#!/bin/bash                                                                                                                                   
ch=`echo "b_d" | sed 's/_/\\\\\\\\_/'`
echo $ch

the output is

b\_d

The output from the terminal is the preferred one. What is the solution for using the shell script? Also accepted as answers are ideas how to modify

ch=`echo "b_d" | sed 's/_/\\\\\\\\_/'`

for sh.

I use the bash shell:

echo $0
bash
Viesturs
  • 933
  • 3
  • 10
  • 15
  • 1
    What bash version do you use? I cannot repeat your problem. – schily Aug 25 '18 at 09:18
  • 3
    [`sh` is not `bash`](https://mywiki.wooledge.org/BashGuide/CommandsAndArguments#Scripts). Also, if you run `$SHELL foo.sh` the shebang line is *ignored*. Please show us **exactly** what you are running. – l0b0 Aug 25 '18 at 09:25
  • @I0b0, I updated the question – Viesturs Aug 25 '18 at 11:32

1 Answers1

2

sh differs from bash and behaves different.

I guess that sh is really dash.

BTW: there is different behavior with this command if you check different shells.

bosh, dash, mksh, zsh as well as ksh on Solaris print one backslash

bash and ksh on Linux print two backslashes.

From looking at the $shell -x output, I believe that one backslash is the correct output.

I have no idea why ksh behaves this way on Linux. It could be that it tries to mimic bash behavior.

For bash the behavior can be explained: bash has a non-POSIX echo that does not interpret backshlashes as required by POSIX.

POSIX permits the behavior of bash only on small embedded systems and POSIX otherwise requires the so called XSI extensions to be implemented. With echo, this requires to fully follow the behavior of echo as impleented in 1982 by AT&T for SYSv.

An important note:

If you have a script that starts with

#!/bin/bash

and that is executable (x bit set bychmod), and if you call

sh myscript

this script is still run by /bin/sh which is typically dash on Linux. So be careful on how you run your code.

There is a way to avoid your problem. Change your script to use:

ch=`echo "b_d" | sed 's/_/\\\\\\\\_/'`
printf '%s\n' $ch

This way, you avoid the problems with echo that have been introduced in 1989 with bash. printf does still not solve all problems since there are many buggy implementations, but the usual problems that arise from backslashes in the arguments are not affected by printf.

schily
  • 18,806
  • 5
  • 38
  • 60
  • Could you please highlight in your answer to replace `sh` by `bash` in `sh script.sh`, as it solved my problem. – Viesturs Aug 25 '18 at 11:36
  • 1
    [_"If the first operand is -n, or if any of the operands contain a character, the results are implementation-defined."_](http://pubs.opengroup.org/onlinepubs/9699919799.2018edition/utilities/echo.html)... – ilkkachu Aug 25 '18 at 11:52
  • 1
    This is a missinterpretation of the POSIX standard. POSIX requires full `XSI` compliance for shells that are used on non-embedded systems. Note that my answer is verified by an related answer from Geoff Clare, the author of the POSIX certification test suite. – schily Aug 25 '18 at 11:59
  • I think you need to add @ilkkachu to your comment. – Viesturs Aug 25 '18 at 12:36
  • @schily, can you add a link to that answer? – ilkkachu Aug 25 '18 at 12:43
  • @ilkkachu That was in a POSIX teleconference call, there is no related text. BTW: as a result, I decided to include support for the useless `fc` command in `bosh` since I like `bosh` to be POSIX compliant. Geoff told me that there is no support to remove the `fc` command from the`XSI` list. – schily Aug 25 '18 at 12:44
  • A more comprehensive explanation can be found at https://unix.stackexchange.com/a/65819/5132 . – JdeBP Aug 25 '18 at 20:17
  • In a writing of that length, it would be nice if the order of the first part of the description did match historical order and if itmentioned that the escape secuence `\c` has been introduced in the mid 1970s with `troff` already. Also mentioning UNIX V8 would need to explain it's position in the timeline as it is not the successor of UNIX V7. – schily Aug 26 '18 at 13:56