• awk的递归


      版权申明:本文为博主窗户(Colin Cai)原创,欢迎转帖。如要转贴,必须注明原文网址
    
      http://www.cnblogs.com/Colin-Cai/p/9082551.html 
    
      作者:窗户
    
      QQ:6679072
    
      E-mail:6679072@qq.com
    

      想来惭愧,之前写的一篇文章《用awk写递归》里多少是传递了错误的信息。虽然那篇文章目的上是为了给出一种思路,但实际上awk是可以支持函数局部变量的。

      awk对于局部变量的支持比起大多数过程式语言来说很是怪异,它只在函数的参数里支持。所以如果想用局部变量,多少需要改变我们以前的一些习惯。

      于是我们使用这一点,就可以直接写出一个awk下面的递归。举个简单的例子,比如我们想输入一个数n,就算出1+2+...n的值。写法如下:

      

    awk '
            function sum(n, other_sum)
            {
                    return n==0?other_sum:sum(n-1, other_sum+n)
            }
            {
                    print sum($1,0)
            }'
    

      sum在这里作为一个递归,接受两个参数,一个是n,一个是之前的累和结果。这种用法很像函数式编程,比如lisp系。

      以Scheme为例

      

    (define (sum n)
       (define (_sum n other_sum)
        (if (= n 0) other_sum (_sum (- n 1) (+ other_sum n))))
       (_sum n 0)
       )

      为了忏悔,我还是用awk写个函数式风格的汉诺塔程序吧。

    #!/usr/bin/awk -f
    function connect(a, b)
    {
            return a "" b
    }function other_pos(a, b)
    {
            return 6-a-b;
    }
    
    function sub1(a)
    {
            return a-1;
    }
    
    function eq(a, b)
    {
            return a==b;
    }
    
    function hanoi2(n, from, to)
    {
            return eq(n,0)? "": connect(connect(connect(hanoi2(sub1(n), from, other_pos(from,to)), " "),connect(from, "->")),connect(connect(to, " "),hanoi2(sub1(n), other_pos(from,to), to)))
    }
    function hanoi(n)
    {
            return hanoi2(n, 1, 3)
    }
    {
            print hanoi($1)
    }

      运行一下,尝试一下8块饼的汉诺塔怎么移动。

      

    $ echo 8 | ./hanoi.awk
    1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3 1->2 3->1 3->2 1->2 3->1 2->3 2->1 3->1 3->2 1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3 2->1 3->1 3->2 1->2 3->1 2->3 2->1 3->1 2->3 1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3 1->2 3->1 3->2 1->2 3->1 2->3 2->1 3->1 3->2 1->2 1->3 2->3 1->2 3->1 3->2 1->2 3->1 2->3 2->1 3->1 2->3 1->2 1->3 2->3 2->1 3->1 3->2 1->2 3->1 2->3 2->1 3->1 3->2 1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3 1->2 3->1 3->2 1->2 3->1 2->3 2->1 3->1 3->2 1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3 2->1 3->1 3->2 1->2 3->1 2->3 2->1 3->1 2->3 1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3 2->1 3->1 3->2 1->2 3->1 2->3 2->1 3->1 3->2 1->2 1->3 2->3 1->2 3->1 3->2 1->2 3->1 2->3 2->1 3->1 2->3 1->2 1->3 2->3 2->1 3->1 3->2 1->2 3->1 2->3 2->1 3->1 2->3 1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3 1->2 3->1 3->2 1->2 3->1 2->3 2->1 3->1 3->2 1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3 2->1 3->1 3->2 1->2 3->1 2->3 2->1 3->1 2->3 1->2 1->3 2->3 1->2 3->1 3->2 1->2 1->3 2->3 2->1 3->1 2->3 1->2 1->3 2->3

      注意,前面写函数式风格的时候,我最终还是使用了三目条件运算符,而没有搭建一个函数 

      function cond_op(cond, a, b)
      {
        return cond?a:b;
      }

      因为如果这样搭建,必然会死循环,想想为什么?

  • 相关阅读:
    『重构--改善既有代码的设计』读书笔记----Replace Temp with Query
    LXPanel自定义添加应用程序到快速启动栏
    『重构--改善既有代码的设计』读书笔记----Inline Temp
    『重构--改善既有代码的设计』读书笔记----Inline Method
    App Store自动下载WiFi与蜂窝数据切换机制
    『重构--改善既有代码的设计』读书笔记----Extract Method
    EXpression 表达式目录树
    linq to sql and linq to object 总结
    基于反射实现实体DTO映射
    对文件操作
  • 原文地址:https://www.cnblogs.com/Colin-Cai/p/9082551.html
Copyright © 2020-2023  润新知