What are the differences in echo between zsh and bash?

余生长醉 提交于 2021-01-28 10:50:46

问题


In bash, in this specific case, echo behaves like so:

$ bash -c 'echo "a\nb"'
a\nb

but in zsh the same thing turns out very differently...:

$ zsh -c 'echo "a\nb"'
a
b

and fwiw in fish, because I was curious:

$ fish -c 'echo "a\nb"'
a\nb

I did realize that I can run:

$ zsh -c 'echo -E "a\nb"'
a\nb

But now I am worried that I'm about to stumble into more gotchas on such a basic operation. (Thus my investigation into fish: if I'm going to have to make changes at such a low level for zsh, why not go all the way and switch up to something that is blatant about being so different?)

I did not myself find any documentation to help clarify this echo difference in bash vs zsh or pages directly listing the differences, so can someone here list them out? And maybe direct me to any broader set of potentially impactful gotchas when making the switch, that would cover this case?


回答1:


Usually prefer printf for consistent results.

If you need predictable consistent echo implementation, you can override it with your own function.

This will behave the same, regardless of the shell.

echo(){ printf %s\\n "$*";}
echo "a\nb"



回答2:


echo is good and portable only for printing literal strings that end with a newline but it's not good for anything more complex, you can read more about it in this answer and in Shellcheck documentation here.

Even though according to POSIX each implementation has to understand character sequences without any additional options you cannot rely on that. As you already noticed, in Bash for example echo 'a\nb' produces a\nb but it can be changed with xpg_echo shell option:

$ echo 'a\nb'
a\nb
$ shopt -s xpg_echo
$ echo 'a\nb'
a
b

And maybe direct me to any broader set of potentially impactful gotchas when making the switch, that would cover this case?

Notice that the inconsistency between different echo implementations can manifest itself not only in shell but also in other places where shell is used indirectly, for example in Makefile. I've once come across Makefile that looked like this:

all:
    @echo "target\tdoes this"
    @echo "another-target\tdoes this"

make uses /bin/sh to run these commands so if /bin/sh is a symlink to bash on your system what you get is:

$ make
target\tdoes this
another-target\tdoes this

If you want portability in shell use printf. This:

printf 'a\nb\n'

should produce the same output in most shells.



来源:https://stackoverflow.com/questions/64079604/what-are-the-differences-in-echo-between-zsh-and-bash

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!