如何将一个变量分割成数组索引?

4
这是一个典型的问题:给定一组值,检查它们是否存在于数组中。
awk中,技巧val in array非常有效。因此,典型的想法是将所有数据存储在数组中,然后不断进行检查。例如,这将打印所有第一列值存在于该数组中的行。
awk 'BEGIN {<<initialize the array>>} $1 in array_var' file

然而,初始化数组需要一些时间,因为val in array检查索引val是否在array中,而我们通常存储在array中的是一组值。
当从命令行提供值时,这变得更加相关,因为这些值是我们想要包含作为数组索引的元素。例如,在这个基本示例中(基于我最近回答的一个问题,这激发了我的好奇心):
$ 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[]变量。

除了设置一个变量并使用它的值作为最终数组的索引之外,还有更快的初始化数组索引的方法吗?

2个回答

3

不,那是最快的方法(由于哈希查找)和最稳健的方法(由于字符串比较),以实现您想要的功能。

这个:

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

1
正则表达式比哈希查找慢,因此在性能方面可能会有所不同,您还必须处理数据中的正则表达式元字符,以避免产生错误匹配。 - Ed Morton

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