AWK咖喱函数 - 函数可以返回函数吗?

时间:2017-01-30 17:35:46

标签: awk gawk currying awk-formatting

我正在研究一个当前非常混乱的AWK脚本,并且我正在努力改进它(主要是因为我想提高我的Awk脚本技能)

我意识到在Awk或Gawk中没有一种方法可以进行面向对象的编程,但是有没有办法至少可以解决函数问题?在从函数内返回函数时? (不返回执行函数的结果,而是返回可以执行的函数)

我找到了一个Stack Overflow post,其中@GreenFox表明它可以执行一个函数,该函数具有存储在变量中的函数的名称。他发布的例子如下:

function foo(s){print "Called foo "s}
function bar(s){print "Called bar "s}
{
    var = "";
    if(today_i_feel_like_calling_foo){
        var = "foo";
    }else{
        var = "bar";
    }
    @var( "arg" ); # This calls function foo(), or function bar() with "arg"
}

我想知道的是它是否可以从另一个函数返回一个函数。

例如,一个函数接受一个可以在awks printf中用作格式的字符串,并返回一个接受另外两个参数的函数,并基本上执行printf( fmt_from_parent_func, sub_func_arg1, sub_func_arg2 )

这是我试图完成以下任务的尝试:

#! /usr/local/bin/awk -f

function setFmt ( fmt ){
  function _print ( var, val ){
    printf ( fmt ? fmt : "%-15s: %s\n" ), str1, str2
  }
  return @_print
}
BEGIN {
  fmtA = setFmt("%-5s: %s\n")
  @fmtA("ONE","TWO")
}

导致错误:

awk: ./curry.awk:4:   function _print ( var, val ){
awk: ./curry.awk:4:   ^ syntax error
awk: ./curry.awk:4:   function _print ( var, val ){
awk: ./curry.awk:4:                               ^ syntax error
awk: ./curry.awk:6:     printf ( fmt ? fmt : "%-15s: %s\n" ), str1, str2
awk: ./curry.awk:6:                                                     ^ unexpected newline or end of string
awk: ./curry.awk:11:   fmtA = setFmt("%-5s: %s\n")
awk: ./curry.awk:11:                              ^ unexpected newline or end of string
awk: ./curry.awk:12:   @fmtA("ONE","TWO")
awk: ./curry.awk:12:                     ^ unexpected newline or end of string

如果有人知道这是否完全可能(我开始看到自己),并且知道如何实现某种效果......那将是非常棒的。

谢谢!

1 个答案:

答案 0 :(得分:2)

使用GNU awk,您可以将函数的名称作为字符串从另一个函数返回但是您不能在另一个函数中声明函数,也不能在任何awk中返回函数(或数组) - 所有您都可以返回来自awk中的函数是标量值(即数字或字符串)。

这是你要做的事情:

$ cat tst.awk
function _print ( var, val ){
  printf _print_fmt, var, val
}

function setFmt ( fmt ){
  _print_fmt = (fmt ? fmt : "%-15s: %s\n" )
  return "_print"
}

BEGIN {
  fmtA = setFmt("%-5s: %s\n")
  @fmtA("ONE","TWO")
}

$ awk -f tst.awk
ONE  : TWO