bash power set功能背后的逻辑

时间:2013-04-01 10:48:19

标签: algorithm bash recursion

该功能(输出给定输入的功率集)

p() { [ $# -eq 0 ] && echo || (shift; p "$@") |
        while read r ; do echo -e "$1 $r\n$r"; done }

测试输入

p $(echo -e "1 2 3")

测试输出

1 2 3
2 3
1 3
3
1 2
2
1

我在以下代码中难以掌握递归。我尝试通过在代码中放置一些变量来表示递归级别和执行顺序来理解它,但我仍然感到困惑。

到目前为止,我可以告诉以下事项:

  1. 子shell的输出不会显示在最终输出上,因为它会通过管道重定向到读取命令
  2. echo命令为其所有输出添加新行
  3. 我看到的执行顺序是:

    1. p(1 2 3) - > 1后面是\ n的所有输出组合                 
    2. 下面的所有输出组合
    3. p(2 3) - > 2 3 \ n3 \ n
    4. p(3) - > 3
    5. p() - >
    6. 所以我认为在执行#3时我应该有p(2)而不是p(3),但是这是怎么回事?由于shift仅朝一个方向发展。

      如果我使用“p(1 2 3 4)”作为输入,则输出中显示“1 2 3”的部分会让我感到困惑。

1 个答案:

答案 0 :(得分:3)

-e命令中使用echo在我看来是纯粹的混淆,因为它可以写成:

p() { [ $# -eq 0 ] && echo || (shift; p "$@") |
      while read r ; do
        echo $1 $r
        echo $r
      done
    }

换句话说,“对于除第一个参数(shift; p "$@")之外的所有集合中的每个集合,输出带有和不带第一个参数的集合。”

bash函数的工作方式是设置一个子shell链,每个子shell读取下一个,就像这样,每个盒子都是一个子shell,在它下面,我已经显示了它的输出,因为它读取了每一行输入:(我使用""使“无”可见。=>表示“通话”; <-表示“阅读”。)

+---------+     +-------+     +-------+     +-------+
| p 1 2 3 | ==> | p 2 3 | ==> |  p 3  | ==> |   p   |
+---------+     +-------+     +-------+     +-------+
  1 2 3 "" <--+-- 2 3 "" <---+-- 3 "" <-----+-- ""
  2 3 ""   <-/              /              /
  1 3 ""   <--+-- 3 ""   <-/              /
  3 ""     <-/                           /
  1 2 ""   <--+-- 2 ""   <---+-- ""   <-/
  2 ""     <-/              /
  1 ""     <--+-- ""     <-/
  ""       <-/