1

我是 Unix 新手,并且在基于具有连字符索引的字段连接两个制表符分隔的文本文件时遇到了麻烦。例如:

file1.txt
33-47   10      22      -99     10
33-48   15      22      165     456
33-101  10      22      -99     15.8
33-126  10      22      -99     15.5
34-133  10      22      -99     13
40-109  10      22      -99     12
41-102  88      21      -99     20
45-169  54      214     -99     4
100-11  652     524     87      5
101-25  45      54      153     8
101-26  1285    12      155     9.5

file2.txt
1       5432    545     33-101
1       5524    5420    33-126
0       855520  52220   33-47
0       5463    5420    34-133
0       5563    5423    40-109
1       6098    -99     40-109

本质上,文件 1 是一个查找表,我想将文件 1 的匹配行附加到文件 2 以创建一个完整的变量表,即:

file3.txt (expected)
1       5432    545     33-101  10      22      -99     15.8
1       5524    5420    33-126  10      22      -99     15.5
0       855520  52220   33-47   10      22      -99     10
0       5463    5420    34-133  10      22      -99     13
0       5563    5423    40-109  10      22      -99     12
1       6098    -99     40-109  10      22      -99     12

我正在使用 Cygwin,并尝试首先以数字方式对字段进行排序,通常使用 LC_COLLATE=C 语言环境以及许多 awk NR==FNR 命令,但我仍然得到一个空白文件。

这都是新的,非常令人沮丧。如果可以的话请帮忙!

谢谢!

4

2 回答 2

1

这对我有用,但我不在 Cygwin 上:

awk 'NR==FNR{info[$1]=gensub(/[^\t]*\t/,"",1)} NR!=FNR{printf"%s\t%s\n",$0,info[$NF]}' file1.txt file2.txt

我相信有人可以改进...

于 2012-05-23T18:35:58.617 回答
1

我很想知道你是怎么工作join的。

这是一个非常丑陋的方式:

a='{split($f, a, /-/); $f = sprintf("%05d%05d", a[1], a[2]); print}'
join -1 4 -2 1 -o 1.1 1.2 1.3 0 2.2 2.3 2.4 2.5 2.6 2.7 2.8 \
    <(awk -v f=4 "$a" file2.txt | sort -k4,4) | 
    <(awk -v f=1 "$a" file1.txt | sort) \
    awk 'BEGIN {OFS = "\t"} {$4 = substr($4, 1, 5) + 0 "-" substr($4, 6, 5) + 0; print}'

输出:

0       855520  52220   33-47   10      22      -99     10
1       5432    545     33-101  10      22      -99     15.8
1       5524    5420    33-126  10      22      -99     15.5
0       5463    5420    34-133  10      22      -99     13
0       5563    5423    40-109  10      22      -99     12
1       6098    -99     40-109  10      22      -99     12

如果您省略了-o输出规范(并在 final中将字段从更改为$4to ),从而缩短了命令,则输出将如下所示(公共字段优先):$1awk

33-47   0       855520  52220   10      22      -99     10
33-101  1       5432    545     10      22      -99     15.8
33-126  1       5524    5420    10      22      -99     15.5
34-133  0       5463    5420    10      22      -99     13
40-109  0       5563    5423    10      22      -99     12
40-109  1       6098    -99     10      22      -99     12

上面的方法是在键字段中左填充数字并删除连字符,然后再撤消它。这允许进行简单的词法排序。

我很想使用sort -V(版本排序)而不是使用填充技术。它给出了正确的排序顺序,但join不同意。

于 2012-05-24T02:10:57.710 回答