【问题标题】:How to slice a variable into array indexes?如何将变量切片为数组索引?
【发布时间】:2016-11-28 14:24:07
【问题描述】:

有一个典型的问题:给定一个值列表,检查它们是否存在于数组中。

awk 中,技巧val in array 确实很有效。因此,典型的想法是将所有数据存储在一个数组中,然后继续进行检查。例如,这将打印数组中第一列值存在的所有行:

awk 'BEGIN {<<initialize the array>>} $1 in array_var' file

但是,初始化数组需要一些时间,因为val in array 会检查索引val 是否在array 中,而我们通常存储在array 中的是一组值。

当从命令行提供值时,这变得更加相关,其中那些是我们想要包含为数组索引的元素。例如,在这个基本示例中(基于recent answer of mine,这引发了我的好奇心):

$ cat file
hello 23
bye 45
adieu 99
$ awk -v values="hello adieu" 'BEGIN {split(values,v); for (i in v) names[v[i]]} $1 in names' file
hello 23
adieu 99
  • split(values,v) 将变量 values 分割成数组 v[1]="hello"; v[2]="adieu"
  • for (i in v) names[v[i]]names["hello"]names["adieu"] 用空值初始化另一个数组names[]。这样,我们就准备好了
  • $1 in names 检查第一列是否是 names[] 中的任何索引。

如您所见,我们切入一个临时变量 v,以便稍后初始化最终的有用变量 names[]

有没有更快的方法来初始化数组的索引,而不是设置一个然后使用它的值作为确定的索引?

【问题讨论】:

    标签: arrays awk gawk


    【解决方案1】:

    不,这是最快(由于哈希查找)和最健壮(由于字符串比较)的方式来做你想做的事。

    这个:

    BEGIN{split(values,v); for (i in v) names[v[i]]}
    

    在启动时发生一次,在此期间几乎不需要任何时间:

    $1 in array_var
    

    每行输入都会发生一次(需要获得最佳性能的地方也是如此)是哈希查找,因此是将字符串值与一组字符串进行比较的最快方法。

    【讨论】:

      【解决方案2】:

      不是数组解决方案,但一个技巧是使用模式匹配。为了消除部分匹配,用分隔符包装搜索和数组值。以您为例,

      $ awk -v values="hello adieu" 'FS values FS ~ FS $1 FS' file
      hello 23
      adieu 99
      

      【讨论】:

      • 正则表达式比较比哈希查找慢,因此 YMMV 具有执行此操作的性能,然后您必须处理数据中产生错误匹配的正则表达式元字符。
      猜你喜欢
      • 2018-03-02
      • 2017-11-29
      • 1970-01-01
      • 1970-01-01
      • 2018-06-16
      • 2015-01-21
      • 2020-04-01
      • 1970-01-01
      相关资源
      最近更新 更多