避免修剪bash $()输出

时间:2010-12-07 12:30:51

标签: bash newline

来自Bash手册:

  

Bash通过执行扩展   执行命令并替换   命令用标准替换   输出命令,任何   尾随新行已删除。

这意味着在处理具有有意义的尾随换行符的输出时,可能会出现模糊的错误。一个人为的例子:

user@host:~$ path='test

'
user@host:~$ touch -- "$path"
user@host:~$ readlink -fn -- "$path"
/home/user/test

user@host:~$ full_path="$(readlink -fn -- "$path")"
user@host:~$ ls -- "$full_path"
ls: cannot access /home/user/test: No such file or directory

有关如何在不丢失语义上有用的数据的情况下将命令值赋给变量的任何提示?

Bash的冒险经历了另一天!

4 个答案:

答案 0 :(得分:7)

您可以使用引号和eval来解决此问题。将最后两个命令更改为:

full_path="'$(readlink -fn -- "$path"; echo \')"
eval ls -- "$full_path"

如果您希望结果在变量中包含尾随换行符,您可以先添加一个虚假字符(在本例中为下划线),然后将其删除。

full_path="$(readlink -fn -- "$path"; echo _)"
full_path=${full_path%_}
ls -- "$full_path"

答案 1 :(得分:1)

我没有好的答案。但是,这个hack将适用于名称中包含和不包含换行符的文件。

path='test

'
touch -- "$path"
readlink -fn -- "$path"
full_path=
if [[ $path =~ $'\n' ]] ; then
        while IFS=$'\n' read fn ; do
                full_path+="$fn"$'\n'
        done < <(readlink -fn -- "$path")
else
        full_path="$(readlink -fn -- "$path")"
fi
ls -l -- "$full_path"

答案 2 :(得分:0)

一种(弃用)方式可能是使用反引号而不是$();尝试:

full_path=`readlink -fn -- $path`

答案 3 :(得分:0)

$ readlink -f "$path"

这回归好路。我不知道为什么你使用了带有readlink的-n选项,因为它删除了换行符。

不幸的是,当我存储此命令的结果时,新行似乎已被删除

$ fullpath=`readlink -f "$path"`
$ echo "$fullpath"
/home/test

没有换行。我不知道它是“回声”还是在路径末端删除换行符的存储方式。

$ ls
test?
$ls test?
test?

Newline似乎被替换为?可能与它有关。