【问题标题】:gawk and PROCINFO not working as expected with sorting longer length stringsgawk 和 PROCINFO 无法按预期对较长的字符串进行排序
【发布时间】:2020-11-12 15:27:06
【问题描述】:

假设我有一个简单的小字符串文件,我想按行长排序:

$ cat file1
123
2
45
12345
123456789
1

我可以编写一个gawk 脚本,使用函数和PROCINFO["sorted_in"] 对这些字符串进行排序:

$ gawk 'function cmp_len(i1, v1, i2, v2) {
            return length(v1) - length(v2)
      }
      NR==FNR{arr[$0]; next}
      END{PROCINFO["sorted_in"] = "cmp_len"
      for (e in arr) print e
      } 
      ' file1
1
2
45
123
12345
123456789

完美!

但现在假设我在该文件中添加了一些更长的字符串:

$ cat file2
123
2
45
xyxyxyxyxyyxyxyxyxyxyyxyxyxxyxyxyxyyxyxyxyxyyx
12345
56565656565656565665656566565656656565656
123456789
1

它坏了:

$ gawk 'function cmp_len(i1, v1, i2, v2) {
            return length(v1) - length(v2)
      }
      NR==FNR{arr[$0]; next}
      END{PROCINFO["sorted_in"] = "cmp_len"
      for (e in arr) print e
      } 
      ' file2
123456789
56565656565656565665656566565656656565656
1
2
45
123
12345
xyxyxyxyxyyxyxyxyxyxyyxyxyxxyxyxyxyyxyxyxyxyyx

这样可以正常工作:

$ awk '{ print length()"\t"$0}' file2 | sort -n | cut -f2
# expected output by length...

但这让我正在编写的脚本更加困难。

知道为什么PROCINFO 在此示例中不能使用较长的字符串吗?

【问题讨论】:

  • 除此之外 - 您只有一个输入文件,因此 NR==FNR 始终为真,因此可以删除。
  • @EdMorton:谢谢。我正在编写的脚本有两个,因此剩下了。

标签: sorting awk


【解决方案1】:

来自manual

这里,“i1”和“i2”是索引,“v1”和“v2”是被比较的两个元素的对应值。

您的比较函数是比较数组的,而不是索引。并且值总是空字符串,所以函数总是返回 0。把它改成

function cmp_len(i1, v1, i2, v2) {
         return length(i1) - length(i2)
}            

你会得到你想要的订单。或者更好的是,缓存长度并使用内置比较,因为存储了有意义的值:

gawk '
NR==FNR { arr[$0] = length($0) }
END {
        PROCINFO["sorted_in"] = "@val_num_asc"
        for (e in arr) print e
} 
' file1

【讨论】:

  • 所以第一个示例输出只是随机数?
  • 由于所有条目的比较彼此相等,是的,它只是偶然出现的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-11-26
  • 2021-12-19
  • 2012-12-24
  • 1970-01-01
  • 2016-04-23
  • 2021-04-05
  • 1970-01-01
相关资源
最近更新 更多