具有动态索引的awk数组

时间:2014-05-08 20:37:03

标签: arrays awk

假设我有一个制表符分隔文件lookup.txt

070-031 070-291 030-031
1   2   X
2   3   1
3   4   2
4   5   3
5   6   4
6   7   5
7   8   6
8   9   7

我有以下文件,其中包含要从

查找的值
$cat 030-031.txt
Line1   070-291 4
Line2   070-031 3

$cat 070-031.txt
Line1   030-031 5
Line2   070-291 8

我希望script.awk返回

$script.awk 030-031.txt lookup.txt
Line1   070-291 4   2
Line2   070-031 3   2

$script.awk 070-031.txt lookup.txt
Line1   030-031 5   6
Line2   070-291 8   7

我唯一能想到的就是创建两个单独的扩展lookup.txt,例如

$cat lookup_030-031.txt
070-031:1   X
070-031:2   1
070-031:3   2
070-031:4   3
070-031:5   4
070-031:6   5
070-031:7   6
070-031:8   7
070-291:2   X
070-291:3   1
070-291:4   2
070-291:5   3
070-291:6   4
070-291:7   5
070-291:8   6
070-291:9   7

然后

awk 'NR==FNR { a[$1]=$2;next}{print $0,a[$2":"$3]}' lookup_030-031.txt 030-031.txt

这有效,但我有更多的列和大约10000行,所以我宁愿不必为每个列生成一个查找文件。非常感谢

修改

格伦杰克曼的答案是对最初问题的完美解决方案,他的第二个答案更有效率。但是,我忘了规定脚本应该处理重复。例如,它应该能够处理

$cat 030-031
070-031 3
070-031 6

并返回相应文件的相应数字(分别为2和5)。只有Glens第一个回答处理重复查找。他的第二个返回找到的最后一个值。

2 个答案:

答案 0 :(得分:1)

好的,我现在看到了。您必须将查找文件读入大型数据结构,然后使用单个文件进行引用很容易。

$ cat script.awk 
BEGIN {OFS = "\t"}
NR==1 {
    for (i=1; i<=NF; i++) 
        label[i] = $i
    next
}
NR==FNR {
    for (i=1; i<=NF; i++) 
        for (j=1; j<=NF; j++) 
            if (i != j) 
                value[label[i],$i,label[j]] = $j
    next
}
FNR==1 {
    split(FILENAME, a, /\./)
    j = a[1]
}
{
    $(NF+1) = value[$1,$2,j]
    print
}

$ awk -f script.awk lookup.txt 030-031.txt
070-291 4   2
070-031 3   2

$ awk -f script.awk lookup.txt 070-031.txt 
030-031 5   6
070-291 8   7

此版本更紧凑,并按您的首选顺序传递文件名:

$  script.awk 
BEGIN {OFS = "\t"}

NR==1 {
    split(FILENAME, a, /\./)
    dest = a[1]
}
NR==FNR {
    src[$1]=$2
    next
}
FNR==1 {
    for (i=1; i<=NF; i++)
        col[$i]=i
    next
}

{
    for (from in src)
        if ($col[from] == src[from])
            print from, src[from], $col[dest]
}

$ awk -f script.awk  030-031.txt   lookup.txt 
070-031 3   2
070-291 4   2

$ awk -f script.awk  070-031.txt  lookup.txt 
030-031 5   6
070-291 8   7

答案 1 :(得分:0)

This works but I have many more columns and approximately 10000 rows, so i'd rather not have to generate a lookup file for each.

您的数据集足够小,您可以选择将查找保留在内存中。

BEGIN 部分,阅读&#34; lookup.txt&#34;到一个二维(嵌套)数组,以便:

lookup['070-031'][4] = 3  
lookup['070-291'][5] = 3  

一次性浏览所有数据文件:

script.awk 070-031.txt 070-291.txt