Bash 壳中的技巧支撑展开
当使用POSIX shell时,以下命令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 有没有办法做到这一点?如果需要的话,我不介
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年前(当我问这个问题时)我不知道:)