awk:next在函数

时间:2017-05-17 13:31:02

标签: bash shell awk

我有一个简短的shell函数将人类可读的字节单元转换为字节整数,例如,

10米到10000000 4kb到4000 1kib到1024 2gib到2147483648

以下是代码:

dehumanise() {
    for v in "$@"
    do
        echo $v | awk \
        'BEGIN{IGNORECASE = 1}
        function printpower(n,b,p) {printf "%u\n", n*b^p; next}
        /[0-9]$/{print $1;next};
        /K(B)?$/{    printpower($1, 10,  3)};
        /M(B)?$/{    printpower($1, 10,  6)};
        /G(B)?$/{    printpower($1, 10,  9)};
        /T(B)?$/{    printpower($1, 10, 12)};
        /Ki(B)?$/{printpower($1,  2, 10)};
        /Mi(B)?$/{printpower($1,  2, 20)};
        /Gi(B)?$/{printpower($1,  2, 30)};
        /Ti(B)?$/{printpower($1,  2, 40)}'
    done
}

我在互联网上找到了代码,我对awk并不那么自信。该功能正常,直到我几天前重新安装我的MacBook。现在它抛出一个错误

  

awk:接下来在函数printpower的源代码行2中的函数内是非法的    背景是                   function printpower(n,b,p){printf“%u \ n”,n * b ^ p; >>>下一个}<<<

据我了解,接下来用于awk直接结束记录。因此,在这种情况下,它将结束awk语句,因为它只有一个输入。

我试图将下一个语句简单地移到printpower(...)之后;接下来。 但这导致函数根本没有输出。

有人可以帮我修复awk声明吗?

#awk --version

  

awk版本20121220

macOS awk版

解决

没有输出的东西可能是macOS awk版本的问题。我用gawk安装并替换它:

brew install gawk
brew link --overwrite gawk

现在没有下一个声明就能正常工作。

3 个答案:

答案 0 :(得分:1)

软件设计基础 - 避免控制反转。在这种情况下,您不希望某些从属功能突然负责您的整个处理控制流程,并且 IT 决定"拧紧所有人,我' m 决定跳到下一个记录"。所以是的,不要将next放在函数中!话虽如此,POSIX并没有说你不能在一个函数中使用next但是它没有明确说你可以这样一些awk实现(显然你正在使用的那个)决定在gawk和其他一些awks允许时禁止它它

您的脚本(IGNORECASE)中也有特定于gawk的代码,因此无论如何它只能与gawk一起使用。

以下是如何真正编写脚本以在任何awk中工作:

awk '
    { $0=tolower($0); b=p=0 }
    /[0-9]$/ { b =  1; p =  1 }
    /kb?$/   { b = 10; p =  3 }
    /mb?$/   { b = 10; p =  6 }
    /gb?$/   { b = 10; p =  9 }
    /tb?$/   { b = 10; p = 12 }
    /kib$/   { b =  2; p = 10 }
    /mib$/   { b =  2; p = 20 }
    /gib$/   { b =  2; p = 30 }
    /tib$/   { b =  2; p = 40 }
    p { printf "%u\n", $2*b^p }
'

如果您愿意,可以在主体中的每次; next分配后添加p,但它不会影响输出,只需提高效率,如果您的输入是数千线条很长。

答案 1 :(得分:0)

如消息所示,您无法在函数中使用my_reader[client_list[i]] 。您必须在每个函数调用之后放置它:

next

但如果你不介意额外的CPU周期,你可以让 /KB?$/ { printpower($1, 10, 3); next; } /MB?$/ { printpower($1, 10, 6); next; } ... 测试剩余的模式(在任何地方没有awk)。请注意,next周围的括号是多余的,我已将其删除。

B

答案 2 :(得分:0)

您可以在函数中使用控制变量,然后检查变量的值以决定在主例程中使用下一步。

  # MAIN
      {
      myfunction(test)  
      if (result == 1) next  
      # result is not 1, just continue  
      # more statements  
      }  

      function myfunction(a) {  
        # default result is 0  
        result = 0  
        # some test  
        if ($1 ~ /searchterm/) {  
          result = 1  
        }  

      }