【问题标题】:Join on hyphenated index field in Unix在 Unix 中加入连字符索引字段
【发布时间】:2012-05-30 05:23:20
【问题描述】:

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

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 命令,但我仍然得到一个空白文件。

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

谢谢!

【问题讨论】:

    标签: unix join merge awk


    【解决方案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
    

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

    【讨论】:

    • 这太棒了,对我有用。我还发现加入工作,但我的一些文件有空格把它全部扔掉。如果您有时间翻译,我将不胜感激!
    • 一些解释:读取 file1 (NR==FNR) 构建数组信息。索引是第一列中的值(awk 使用字符串作为索引)数组 info[xx-yy] 的值是字符串 = 行的其余部分 gensub 取行 ($0) 并替换以 tab /[^\t] 结尾的第一个字符串*\t/ 由一个空字符串。这将删除第一列。 gensub 的第三个参数表示仅替换第一个匹配项。 /[^\t]*\t/ :正则表达式匹配许多非制表符字符,后跟一个制表符。读取 file2 (NR!=FNR) $NF : 每行的最后一个单词。恰好匹配数组信息的索引。打印行 ($0),追加 info[$NF] 的值
    【解决方案2】:

    我会非常想知道您是如何让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 输出规范(并在最后的awk 中将字段从$4 更改为$1),从而缩短命令,这就是输出的样子(公共字段优先):

    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 不同意。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-05
      • 2017-02-08
      • 2012-07-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-03-06
      相关资源
      最近更新 更多