在循环中使用数组索引的GNU awk怪异行为

4

我之前在为一个问题(实际上是这个)草拟解决方案,以下是简化版:

$ echo {a..g} | tr ' ' '\n' |  # create some data
  awk  -v s=e '{               # search string as an argument
      for(i=1;i<=2;i++)        # keep 2 last records in a
          a[i]=a[i+1]          # this is the problematic part later
      a[3]=$1                  # hash the current record into a
  }
  $1==s {                      # once there is a match
      for(i=1;i<=3;i++)        # output from the hash
          print a[i]
  }'

输出:

c
d
e

作为我,我必须尝试让它更短一些(从for中删除i++a[i+1]->a[++i])。
$ echo {a..g} | tr ' ' '\n' | 
gawk -v s=e '{
    # i=1; while(i<=2)  # fails with while also
    for(i=1;i<=2;)      # i++ moved
        a[i]=a[++i]     # ... here
    a[3]=$1
}
$1==s {
    for(i=1;i<=3;i++)
        print a[i]
}'

但是,GNU awk 的输出失败了:

    
e

过了一会儿我换成了 mawk,它正常工作。它也可以在 Busybox awk 上工作,但在 awk-20121220 上失败了。有什么想法可以解决这个问题吗?另外,如果您们有更具描述性的标题,请随意更改。


1
你可以简化你的脚本为BEGIN{ a[1]=5; a[2]=15; a[++i]+=a[++i]; print a[1], a[2] }以复现相同的行为。Gawk先计算等号后面的部分,具体原因我不知道。 - oguz ismail
1
@oguzismail 是的,那基本上就是解释了。 - James Brown
1
哈哈,那么我该怎么混淆这个代码呢,“for(i=2;i<=3;) a[i+=2]=a[i--]”不起作用。 :D:D 在半夜的时候绝对不是思考这个问题的好时间... - James Brown
1
for(i=1;i<=2;) a[i++]=a[i+1]for(i=1;i<=2;) a[i-1]=a[++i],或者只需将循环倒回。 - oguz ismail
1个回答

4

来自GNU Awk用户指南:

It is up to the implementation as to which expression is evaluated first, the lefthand or the righthand. Consider this example:

i = 1
a[i += 2] = i + 1

The value of a[3] could be either two or four.


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接