在阅读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>
答案 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
正如@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
。