【问题标题】:Using Bash array in AWK在 AWK 中使用 Bash 数组
【发布时间】:2014-03-19 10:19:13
【问题描述】:

我有两个文件如下:

file1:

3 1
2 4
2 1

file2:

23
9
7
45

file1 的第二个字段用于指定file2 包含要检索和打印的数字的行。在所需的输出中,打印file1 的第一个字段,然后打印检索到的字段。

所需的输出文件:

3 23
2 45
2 23

这是我解决这个问题的尝试:

IFS=$'\r\n' baf2=($(cat file2));echo;awk -v av="${baf2[*]}"  'BEGIN {split(av, aaf2, / /)}{print $1, aaf2[$2]}' file1;echo;echo ${baf2[*]}

但是,此脚本不能使用 Bash 数组 baf2。

解决方案必须高效,因为file1 有数十亿行,而file2 在实际情况下有数百万行。

【问题讨论】:

标签: arrays linux bash awk


【解决方案1】:

你可以使用这个awk

awk 'FNR==NR {a[NR]=$1;next} {print $1,a[$2]}' file2 file1
3 23
2 45
2 23

对数组 a 中的 file2 进行排序。
然后从file1打印字段1并使用字段2在数组中查找。

【讨论】:

  • 亲爱的@Jotne,如果file1 中的行数为m,file2 中的行数为n,此解决方案的运行时复杂度是多少?它不应该是O(mn),因为m 和n 非常大。
  • 我不知道需要多长时间,但您可以输入time awk 'FNR... 看看需要多长时间。
  • 亲爱的@Jotne,在尝试了您的解决方案后,我意识到我提供的 MWE 并未显示我真实数据集的所有属性。 file1 的第一个字段可能相同。
  • @Kadir 我不知道 MWE 是什么,如果数据不同,请更新您的帖子,或者如果差异很大,请创建一个新帖子。
【解决方案2】:

这与 Jotne 的解决方案有类似的基础,但首先将 file2 加载到内存中(因为它小于 file1):

awk 'FNR==NR{x[FNR]=$0;next}{print $1 FS x[$2]}' file2 file1

说明

FNR==NR 部分表示花括号后面的部分仅在读取file2时执行,而不是file1。当 file2 的每一行被读取时,它被保存在数组 x[] 中,以当前行号为索引。第二组花括号中的部分针对 file1 的每一行执行,它打印行上的第一个字段,后跟字段分隔符(空格),然后是 x[] 中的条目,由该行的第二个字段索引.

【讨论】:

    【解决方案3】:

    使用 awk

    1) 打印 file1 中的所有行,无论是否匹配

    awk 'NR==FNR{a[NR]=$1;next}{print $1,a[$2]}' file2 file1
    

    2) 仅打印匹配行

    awk 'NR==FNR{a[NR]=$1;next}$2=a[$2]' file2 file1
    

    【讨论】:

      猜你喜欢
      • 2011-09-30
      • 2015-09-01
      • 2017-11-25
      • 1970-01-01
      • 1970-01-01
      • 2011-05-02
      • 2011-11-06
      • 2014-08-13
      • 1970-01-01
      相关资源
      最近更新 更多