【问题标题】:How to assign a glob expression to a variable in a Bash script?如何将全局表达式分配给 Bash 脚本中的变量?
【发布时间】:2008-12-15 17:38:54
【问题描述】:

在 bash 脚本中执行以下两行代码时,“ls”会提示文件不存在:

dirs=/content/{dev01,dev02}
ls -l $dirs

当我使用 -x 选项运行脚本时,它似乎在单引号内传递变量(这将防止通配符):

+ dirs=/content/{dev01,dev01}
+ ls -l '/content/{dev01,dev01}'
ls: /content/{dev01,dev01}: No such file or directory

如果我从交互式 shell(无引号)执行“ls”命令,它会返回两个目录。

我一直在阅读 Bash 参考手册 (v 3.2) 并且看不到任何不发生文件名通配的原因(我没有将 -f 传递给 shell),或者我可以设置的任何内容以确保发生 globbing。

【问题讨论】:

    标签: bash glob


    【解决方案1】:

    我认为是展开的顺序:

    展开顺序为:brace expansion,波浪号展开,参数, variable 和算术扩展和 命令替换(在 从左到右的时尚),字 分裂,和pathname expansion

    因此,如果您的变量被替换,则不再发生大括号扩展。这对我有用:

    eval ls $dirs
    

    使用 eval 时要非常小心。它将逐字执行这些东西。所以如果dirs包含f{m,k}t*; some_command,则在ls完成后会执行some_command。它将在当前 shell 中执行你给eval 的字符串。它会将/content/dev01 /content/dev02 传递给ls,无论它们是否存在。将 * 放在这些东西之后使其成为路径名扩展,它将省略不存在的路径:

    dirs=/content/{dev01,dev02}*
    

    我对此不是 100% 确定,但对我来说很有意义。

    【讨论】:

    • 大括号扩展发生在变量扩展之前
    • 是的,就是这个原因。当变量展开时,大括号展开不再发生,因为它在变量展开之前就已经发生了。
    • 如果是这样的话,我会期望“dirs”包含一个由大括号扩展产生的单词列表,这可能适用于也可能不适用于实际的文件系统——但这不会出现发生
    • 路径名扩展将会发生。所以 a=a* ls $a 将扩展为以“a”开头的文件。但不会发生大括号扩展。
    • @JohannesSchaub-litb ls $a 可能会扩展到以 a 开头的文件,但 ls "$a" 不会。在分配给 a 时没有发生扩展
    【解决方案2】:

    Here 是对您正在尝试做的事情的精彩讨论。

    简短的回答是你想要一个数组:

    dirs=(/content/{dev01,dev01})
    

    但是你对结果所做的事情可能会比我想象的要复杂得多。

    【讨论】:

    • 我确实看到了那个帖子,但它似乎对我没有帮助。问题来自以下“ls ${dirs}”,它似乎只获取数组中的第一个条目。我也试过 "set ${dirs};ls $*" 但结果是一样的。
    • 你必须做 ls "${dirs[@]}" 。但它会在分配时将名称扩展到目录。所以 dirs 实际上将包含文件名,而不仅仅是模式
    • 新链接失效
    • 链接失效。下次请引用您所写的部分,这对每个人都会更容易。
    【解决方案3】:

    对于通过谷歌找到这个的人(像我一样),@Peter 和@feoh 的答案是“如何在 bash 脚本中全局变量”的一般解决方案。

    list_of_results=(pattern)
    

    将匹配pattern 的现有文件名保存到数组list_of_results 中。 list_of_results 的每个元素将包含一个文件名、空格和所有元素。

    对于从 0 开始的 <index>,您可以使用 "${list_of_results[<index>]}" 访问每个结果。您可以获得正确引用的整个列表,如 "${list_of_results[@]}"

    【讨论】:

    • 这应该是接受的答案恕我直言。很干净。
    • 此解决方案的一个警告是,如果 pattern 不匹配任何内容,则 list_of_results 的值是一个元素的数组,即 pattern 本身,而不是一个空数组可能已经预料到了……
    • @sxc731 使用shopt -s nullglob 来避免这种情况(另请参阅stackoverflow.com/questions/9126060/…
    【解决方案4】:

    这不是文件名通配,这是大括号扩展。 差异是微妙的,但它存在 - 在文件名通配中,您只会收到现有文件,而在大括号扩展中,您可以生成任何类型的字符串。

    http://www.gnu.org/software/bash/manual/bashref.html#Brace-Expansion

    http://www.gnu.org/software/bash/manual/bashref.html#Filename-Expansion

    现在,这对我有用:

    #!/bin/sh
    dirs=`echo ./{dev01,dev02}`
    ls $dirs
    

    【讨论】:

    • 那么你可以做 dirs=( ./{dev01,dev02} );什么 feoh 说的。但它会在分配时扩大。这可能不是他想要的
    【解决方案5】:

    由于您想要全局文件,您不应该使用大括号扩展。在这种情况下使用大括号扩展是一种反模式,而且绝对是适合这项工作的错误工具。

    你要的是extended globbing:

    shopt -s extglob # likely already set in interactive shells
    
    dirs=/content/@(dev01|dev02)
    ls $dirs
    

    【讨论】:

      【解决方案6】:

      我怀疑您需要的是一个数组,但这会限制您使用较新的 bash。它比使用 eval 更节省。

      dirs=( /"content with spaces"/{dev01,dev02} )
      
      dirs=( /content/{dev01,dev02} )
      ls -l "${dirs[@]}"
      

      /content/{dev01,dev02}
      

      将扩展为:

      "/content/dev01" "/content/dev02"
      

      那些目录的存在与扩展无关。

      当您将变量分配给大括号扩展时,它变得不可预测。

      dirs=/content/{dev01,dev02}
      

      可能变成

      "/content/dev01"
      

      "/content/dev01 /content/dev02"
      

      "/content/dev01" "/content/dev02"
      

      "/content/{dev01,dev02}"
      

      如果您以任何方式引用大括号,它们将不会扩展,因此结果将包含大括号并且几乎没有意义。

      【讨论】:

        【解决方案7】:
        ls `echo $dirs` 
        

        在 cygwin 下工作。

        【讨论】:

        • 不适用于 GNU bash,版本 3.2.17(1)-release (i386-apple-darwin9.0)
        • cygwin下是3.2.39(20)。
        【解决方案8】:

        没有人解决的问题是变量赋值产生了影响。

        dirs=/content/{dev01,dev02}
        

        扩展方式不同于

        echo /content/{dev01,dev02}
        

        问题是如何将展开的结果赋值给dirs

        见:How to use Bash substitution in a variable declaration

        【讨论】:

          猜你喜欢
          • 2017-06-25
          • 2018-12-05
          • 1970-01-01
          • 2013-07-04
          • 1970-01-01
          • 1970-01-01
          • 2013-12-06
          • 2015-03-23
          • 1970-01-01
          相关资源
          最近更新 更多