【问题标题】:Curly brace expansion with two arrays to make every combination使用两个数组进行大括号扩展以进行每个组合
【发布时间】:2023-06-28 00:27:01
【问题描述】:

我可以使用花括号和.. 进行如下组合:

$ echo {"foo","bar"}{1..2}
foo1 foo2 bar1 bar2

如果我有两个数组arr1=("foo" "bar")arr2=(1 2),是否可以实现相同的效果?

例如:

$ echo ${arr1[@]}${arr2[@]}       # Returns "foo bar1 2"
or
$ echo {${arr1[@]}}{${arr2[@]}}   # Returns "{foo bar}{1 2}"

【问题讨论】:

  • 我希望你控制数组的内容。如果arr1=( '$(rm -rf ~)' ),基于eval 的方法不会有好的结局。
  • 我从 /etc/passwd 获取用户主目录列表,然后在每个用户目录中的硬编码文件数组中进行 grepping。我想我已经决定只使用 for 循环... ;)
  • 那么这就提出了一个不同的问题。使用grep,您可以使用grep -f <(printf "%s\n" "${array[@]}") 对多个模式进行grep。请不要问 XY 问题。
  • @KamilCuk, ...所以,我认为 上述用例中的array1是主目录列表,array2是要搜索的文件名列表在这些目录中,因此不一定是他们试图提供给 grep 的模式数组。也就是说——是的,他们应该已经描述了用例,但我不确定这是那个特定的 XY问题。

标签: arrays bash curly-braces


【解决方案1】:

大括号{1..2} 扩展发生在变量扩展之前,因此如果没有eval,就不可能这样做。

只需遍历两个数组并创建所有可能的组合

for i in "${arr1[@]}"; do
   for j in "${arr2[@]}"; do
      echo "$i$j"
    done
done

或者您可以使用eval。要安全地执行此操作,请使用 printf %q 生成数组内容的安全引用版本,如下所示:

printf -v arr1_str '%q,' "${arr1[@]}"; arr1_str=${arr1_str%,}
printf -v arr2_str '%q,' "${arr2[@]}"; arr2_str=${arr2_str%,}
eval "printf '%s\n' {${arr1_str}}{${arr2_str}}"

...您可以在https://ideone.com/HunmC3 看到工作(带有一些故意敌对/棘手的样本数据)

【讨论】:

  • 啊,eval 就是我要找的。为什么那是“邪恶的”?
  • 距离 eval 只差一个字母。 Eval and security issues.
  • @WarBro,见BashFAQ #48。使用eval时不注意通常意味着文件名片段可以作为代码执行,或者发生其他不好的事情。
  • ...这是真的,顺便说一句。 "${arr1[*]}"完全不安全地替换为eval
  • @KamilCuk,您是否接受使用printf %q 替换eval-safe 结果的编辑?
【解决方案2】:

您可以完全按照您的要求使用 GNU 并行:

parallel echo {} ::: "${arr1[@]}" ::: "${arr2[@]}"

(如果你想在一行上输出,你可以通过管道输出到tr -s "\n" " "parallel echo {} ::: "${arr1[@]}" ::: "${arr2[@]}" | tr -s "\n" " "

【讨论】:

    最近更新 更多