首页 > 解决方案 > awk 的行为在我的本地系统和 RedHat 6.5 中有所不同

问题描述

RHEL 6.5 的 GNU awk 版本如下

-bash-4.1$ awk --version
GNU Awk 3.1.7

在 Windows 10 中,我将其视为 -

$ awk --version
GNU Awk 5.0.1, API: 2.0 (GNU MPFR 4.0.2, GNU MP 6.1.2)

AWK 程序使用 awk 内置变量ARGVARGIND. 这与 RHEL 中的系统语言环境有关吗?

base.csv

steve,tignor,ash,michael,jose,sam,joshua
0,0,0,0,0,0,0

file1

tignor,michael,jose
888,9,-2

file2

ash,joshua
77,66

merge.awk

#!/bin/awk
#!/bin/bash

ARGIND==1 && FNR==1{
  split($0, base, ",")
  printf("file,%s\n",$0)
}
ARGIND > 1 && FNR==1{
  split($0, names, ",")
  printf("%s", ARGV[ARGIND])
}
ARGIND > 1 && FNR==2{
  split($0, values, ",")
  for(i in names)
    line[names[i]] = values[i]
  for(i in base){
    if(base[i] in line)
      printf(",%s", line[base[i]])
    else
      printf(",0")
  }
  delete line
  print ""
}

从 Linux 运行导致文件 1 和文件 2 中的值顺序不正确

awk -f merge.awk base.csv file*

file,steve,tignor,ash,michael,jose,sam,joshua
file1,9,-2,0,0,0,888,0
file2,0,0,0,66,0,0,77

但在 Windows 上,它工作得非常好,而且是我想要的方式。

$ awk -f merge.awk base.csv file1.csv file2.csv
file,steve,tignor,ash,michael,jose,sam,joshua
A1.csv,0,888,0,9,-2,0,0
A2.csv,0,0,77,0,0,0,66

任何线索将不胜感激。

标签: awk

解决方案


awk数组是哈希表,其元素的迭代使用for (x in y)以任意顺序发生。不过,GNU awk 有一种方法可以通过设置指定使用的顺序PROCINFO["sorted_in"]但是,这只适用于 GNU awk 4.0 和更新版本;3.X 不支持它)。

以数字升序迭代:

#!/usr/bin/gawk -f

BEGIN { PROCINFO["sorted_in"] = "@ind_num_asc" }
ARGIND==1 && FNR==1{
  split($0, base, ",")
  printf("file,%s\n",$0)
}
ARGIND > 1 && FNR==1{
  split($0, names, ",")
  printf("%s", ARGV[ARGIND])
}
ARGIND > 1 && FNR==2{
  split($0, values, ",")
  for(i in names)
    line[names[i]] = values[i]
  for(i in base){
    if(base[i] in line)
      printf(",%s", line[base[i]])
    else
      printf(",0")
  }
  delete line
  print ""
}

您还可以使用常规 for 循环按顺序迭代元素,并且必须在旧 gawk 版本中这样做(仅包括相关的行/块):

...
basenum = split($0, base, ",")
...
for (i = 1; i <= basenum; i++) {
   if(base[i] in line)
      printf(",%s", line[base[i]])
    else
      printf(",0")
}

推荐阅读