假设我有一个制表符分隔文件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第一个回答处理重复查找。他的第二个返回找到的最后一个值。
答案 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