【问题标题】:Avoid trimming of bash $() output避免修剪 bash $() 输出
【发布时间】:2011-05-21 13:37:38
【问题描述】:

来自 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 的冒险又将继续!

【问题讨论】:

    标签: bash newline


    【解决方案1】:

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

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

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

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

    【讨论】:

    • 我需要将结果存储在带有尾随换行符的变量中。你会怎么做?
    • 真棒黑客。顺便说一句,我当然希望我们能很快在 Linux 中获得一个好的面向对象的 shell。尽管存在其他缺陷,PowerShell 有一个很好的模型来访问对象属性。
    • @10b0:如果你想要一个用于 Linux 的非 POSIX shell,你可以试试 zoidberg,它是一个 Perl shell。当然,此时您仍在与 Perl 打交道。还有其他语言的其他外壳。缺乏类似 PowerShell 的 shell 是由于缺乏需求和愿望,而不是技术挑战。
    【解决方案2】:

    我没有好的答案。但是,此 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"
    

    【讨论】:

      【解决方案3】:

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

      full_path=`readlink -fn -- $path`
      

      【讨论】:

      • 为什么反引号的行为会有所不同?
      • @Sorpigal:我不知道,我已经在我的控制台中尝试过了,它可以工作
      • 不起作用,而且重音符号(又名反引号)未被弃用 - Bash 手册将它们简单地称为“旧式”。
      【解决方案4】:
      $ readlink -f "$path"
      

      这会返回好的路径。我不知道您为什么将 -n 选项与 readlink 一起使用,因为它会删除换行符。

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

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

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

      $ ls
      test?
      $ls test?
      test?
      

      换行符似乎被 ? 取代了。可能与它有关。

      【讨论】:

      • -n 不会删除换行符,它避免在文件名后附加 extra 换行符,因此如果文件名可以在结尾。和几乎所有 *nixes 一样
      猜你喜欢
      • 1970-01-01
      • 2014-02-19
      • 1970-01-01
      • 2010-10-03
      • 1970-01-01
      • 2021-01-21
      • 2017-01-07
      • 2018-03-27
      • 1970-01-01
      相关资源
      最近更新 更多