使用 Bash 脚本生成函数调用的所有可能组合

Posted

技术标签:

【中文标题】使用 Bash 脚本生成函数调用的所有可能组合【英文标题】:Generate all possible combinations of a function call using Bash script 【发布时间】:2013-07-19 17:21:44 【问题描述】:

我有一个源文件,其中包含用 Bash 编写的代码。源文件中定义了一些函数,例如

 - abc(i,j,k)

我需要使用 shell 脚本读取源文件,并且需要生成所有可能的函数调用组合,例如:

输出

 - abc(i,j,k)
 - abc(i,j,)
 - abc(i,,j)
 - abc(,j,k)
 - abc(,,k)
 - abc(i,,)
 - abc(,j,)
 - abc(,,)

对于三个参数,有 8 种组合,因此组合会根据参数的数量增加或减少。

【问题讨论】:

为了回答这个问题,我需要知道讨论的是哪种语言。这个问题是关于哪种 shell 脚本语言的? @AndersonGreen 我正在使用 Bash 找出源文件中定义了哪些函数是问题的一部分吗? @VaughnCato- 我已经找到了找到源文件中定义的函数的解决方案。 【参考方案1】:

bash 的大括号展开可以生成组合:

printf -- "- abc(%s\n" i,,j,,k,

但我假设您希望它比这更有活力。这是看起来很难看的代码,但它可以工作。

while IFS= read -r line; do
    # match a line that looks like a function,
    # and capture the function name and the parameter list
    if [[ $line =~ " - "([[:alnum:]]+)\(([a-z,]+)\) ]]; then
        funcname=$BASH_REMATCH[1]
        # split the comma-separated parameters into an array
        IFS=, read -ra params <<< "$BASH_REMATCH[2]"
        # create the brace-expansion string
        printf -v combos "%s,," "$params[@]"
        # and this is the command to print out the combinations
        cmd=( printf -- "\"- $funcname(%s)\n\"" $combos%, )
        # now evaluate it
        eval "$cmd[@]"
    fi
done <<END
 - abc(i,j,k)
END
- abc(i,j,k)
- abc(i,j,)
- abc(i,,k)
- abc(i,,)
- abc(,j,k)
- abc(,j,)
- abc(,,k)
- abc(,,)

【讨论】:

不错!次要评论:使用内置的printf -v combos ... 备用一个fork,因为它会立即填充变量。 @TrueY .. 你能告诉我是否有替代 printf 命令的方法吗? @vishy,你可以使用 echo,但你为什么不想要 printf? @glenn 我们不能使用 echo 代替 printf -v。正确的??由于 Printf 命令分叉了一个进程,以防在高负载情况下过载。旧版本的 bash 也不支持 printf 命令。 我可以访问带有 bash 2.03 的系统,并且它具有 printf 作为内置函数(但不是 printf -v)。你可以回退到:combos=""; for param in "$params[@]"; do combos="$combos$param,,"; done【参考方案2】:

也许有一个更短的版本。我添加纯bash解决方案:

#!/bin/bash

# extract arguments to $arg
fnc=" - abc(i,j,k)"
pre=$fnc%%(*
post=$fnc##*)
arg=$fnc#*(
arg=$arg%)*

# put arguments to arr array
IFS=, read -a arr <<<"$arg"
num=$#arr[@]

# Generate all output lines
for((i=0; i<1<<num; ++i));
  tmp=()
  for ((j=0; j<num; ++j));
    if ((i & (1<<j))); then tmp[j]=""
    else tmp[j]=$arr[j]
    fi
  
  printf -v tmp ,%s "$tmp[@]"
  echo "$pre("$tmp:1")$post"

输出:

 - abc(i,j,k)
 - abc(,j,k)
 - abc(i,,k)
 - abc(,,k)
 - abc(i,j,)
 - abc(,j,)
 - abc(i,,)
 - abc(,,)

脚本使用变量fnc 作为输入。它分为三个部分:pre,args,post。 args 是数组化的。然后它为每个可能的变化生成输出。

【讨论】:

非常感谢..这就是我想要的。我在内部 for 循环中搞砸了。 @vishy:在内部循环中,它将数字 i 解码为二进制数。如果位为 1,则变量替换为空字符串,如果位为 0,则显示该变量。

以上是关于使用 Bash 脚本生成函数调用的所有可能组合的主要内容,如果未能解决你的问题,请参考以下文章

Bash脚本函数溢出到其他脚本中

如何使用 bash -c 调用 bash 脚本函数 [重复]

python 一个类和函数,它为给定列表构造length = 2的所有可能组合。它使用一个环形循环,每个函数调用

Bash 脚本:如何确保脚本在使用“或”(||) 条件调用的函数中出现任何错误时退出?

swift算法:数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且 有效的 括号组合。

2021-09-19:数字 n 代表生成括号的对数,请你设计一个函数,用于能够生成所有可能的并且有效的括号组合。