在bash中,为什么不使用回声删除换行符呢?

时间:2019-02-28 19:57:53

标签: bash echo

在阅读this SO post后,建议使用“ c样式字符串”(例如$ {COMMAND //)删除bash中的“换行符”(理解为\n而非\r\n) [$'\ t \ r \ n']}),为什么不使用echo呢?换句话说:

foo=$'Apple\nBanana\nCherry\n'
echo $foo
Apple Banana Cherry

OR

foo=$(ls -1)
echo $foo
Jenkinsfile README.md exclude_contents install_kit.sh packaging

这是否会引起意外的副作用或其他问题?如果要求是删除换行符,它似乎比${foo//[$'\n']}

更简单

注意:我知道echo "$foo"保留了换行符,并且如果foo包含\r\n,则echo "$foo"不会在一行上显示所有内容。 / p>

1 个答案:

答案 0 :(得分:5)

是的,echo $foo会引起意想不到的副作用。

问题以路径名扩展

考虑包含以下四个文件的目录:

$ ls
f*  factor  fo?  foo

现在,观察到echo $foo产生了八个文件名的列表:

$ foo=$(ls -1)
$ echo $foo
f* factor fo? foo factor fo? foo foo

这是因为$foo中未引用的echo $foo不仅要进行分词(这消除了换行符),而且还要进行 pathname扩展< / em>。

但是,如果我们在双引号内使用模式替换,则会得到正确的文件列表:

$ echo "${foo//$'\n'/ }"
f* factor fo? foo

出现bash的回声

正如@lurker所指出的那样,echo的行为方式令人惊讶。

考虑一个包含三个文件的目录:

$ ls
-e  \none  \text

现在,尝试:

$ foo=$(ls -1)
$ echo $foo

one     ext

如您所见,文件名已损坏。这是因为echo并非将文件名-e解释为文件名,而是将其解释为打开转义序列解释的选项。因此,字符为反斜杠-n-o-n-e的文件名将变为换行符一。字符为反斜杠-t-e-x-t的文件名将变为tab-ext。

Bash的echo命令与-e被视为要打印的文本的POSIX's echo不兼容。因此,依赖于echo的代码是不可移植的。因此,除其他外,通常recommended的新代码使用printf而不是echo