Bash 壳中的技巧支撑展开

Bash 壳中的技巧支撑展开,bash,shell,brace-expansion,Bash,Shell,Brace Expansion,当使用POSIX shell时,以下命令 touch {quick,man,strong}ly 扩展到 touch quickly manly strongly 它将快速地接触文件、手动地接触文件、强烈地接触文件,但是否可以动态创建扩展?例如,以下内容说明了我想做的事情,但由于扩展顺序的原因,它不起作用: TEST=quick,man,strong #possibly output from a program echo {$TEST}ly 有没有办法做到这一点?如果需要的话,我不介

当使用POSIX shell时,以下命令

touch {quick,man,strong}ly
扩展到

touch quickly manly strongly
它将快速地接触文件
手动地接触文件
强烈地接触文件
,但是否可以动态创建扩展?例如,以下内容说明了我想做的事情,但由于扩展顺序的原因,它不起作用:

TEST=quick,man,strong    #possibly output from a program
echo {$TEST}ly

有没有办法做到这一点?如果需要的话,我不介意约束自己去痛击。我还希望避免循环。扩展应作为任何任意程序的完整参数提供(即程序不能为每个文件调用一次,只能为所有文件调用一次)。我知道xargs,但我希望它可以从shell中以某种方式完成。

在bash中,您可以这样做:

#!/bin/bash
TEST=quick,man,strong
eval echo $(echo {$TEST}ly)
#eval touch $(echo {$TEST}ly)

最后一行已注释掉,但将触及指定文件。

从上述答案中汲取灵感:

$ TEST=quick,man,strong
$ touch $(eval echo {$TEST}ly)

。。。使用
eval
有很多错误。您的要求只有在
eval
下才可能实现,但是您可能想要的很容易实现,而无需求助于bash bug central

使用数组!当您需要在一个数据类型中保留多个项时,您需要(或应该使用)一个数组

TEST=(quick man strong)
touch "${TEST[@]/%/ly}"
这正是您想要的,没有其他建议中引入和隐藏的数千个bug和安全问题

它的工作方式是:

  • “${foo[@]}”
    :通过展开名为
    foo
    的数组的每个元素(正确引用),展开该数组。别忘了引语
  • ${foo/a/b}
    :这是一种参数扩展类型,它将
    foo
    中的第一个
    a
    扩展替换为
    b
    。在这种类型的扩展中,您可以使用
    %
    表示扩展值的结束,有点像正则表达式中的
    $
  • 将所有这些放在一起,“${foo[@]/%/ly}”将展开
    foo
    的每个元素,将其作为单独的参数正确引用,并将每个元素的结尾替换为
    ly

    • Zsh可以轻松做到这一点:

      TEST=quick,man,strong
      print ${(s:,:)^TEST}ly
      
      变量内容以逗号分隔,然后每个元素分布到大括号周围的字符串中:

      quickly manly strongly
      

      正如您所知,该解决方案存在大量问题,这些问题只是隐藏了起来,因为您在测试参数中只使用了字母和逗号。任何在bash中有特殊含义的字符都会把它搞砸,尤其是因为您甚至完全没有引用任何内容。我意识到这是一个使用给定数据的演示,但在现实世界的应用程序中使用此解决方案是一种罪恶。@paxdiablo:您可以使用
      eval echo{$TEST}ly
      而不是
      eval echo$(echo{$TEST}ly)
      。好了,额外的回音没有添加任何内容。@lhunah:你似乎瞧不起
      eval
      。有什么特别的错误会导致问题,或者你简单地认为任何东西都是用<代码> EVA/COD>自动的吗?@ ICOOCRASST:处理数据的黄金法则:“不要合并两个不同上下文的字符串。”如果你违反了这个规则,你就把一个字符串的上下文等同于后者的上下文,这总是一个bug,通常会导致任意代码执行。在本例中,您正在将诸如“quick”、“man”和“strong”之类的数据与诸如“echo”和大括号扩展之类的bash代码合并。结果是,您假装数据是bash代码,而事实并非如此。当“强”变为“强”};rm-rf~;#'你有麻烦了。@lhunah:为什么你认为$TEST的值来自不可信的来源?此外,所谓“bug”,你似乎不是指一个实际的缺陷(有些东西出人意料地出现了),而是指一种风险——一种假设的出错机会。我不认为大多数人会像你使用的那样使用这个词。(尽管我假设我们都同意使用
      eval
      会带来风险,而将eval应用于来自不可信来源的数据实际上是自杀性的。)对于多层次的扩展有何建议?例如,
      echo{a,b}/{c,d}/{e,f}
      给出了
      a/c/e a/c/f a/d/e a/d/f b/c/e b/c/f b/e b/d/f
      ;我可以用数组实现这一点,而不必写循环吗?@sdaau您可以将大括号扩展分配给数组。files=({a,b}/{c,d}/{e,f});触摸“${files[@]}”注意,您可以使用
      #
      而不是
      %
      作为项目前缀:
      ${TEST[@]/#/ly}
      给出
      lyquick lyman lystrong
      括号扩展在POSIX外壳中没有定义:@pabouk:没错,现在我知道括号扩展不是POSIX,但7年前(当我问这个问题时)我不知道:)