【问题标题】:properly join two files based on 2 columns in common:基于 2 列共同正确连接两个文件:
【发布时间】:2013-09-29 19:48:54
【问题描述】:

我有两个文件正在尝试根据第 1 列和第 2 列加入/合并。 它们看起来像这样,“文件 1”比文件 2 短得多,我想找到这两个文件的交集: 如果记录不匹配,最后一列需要用不同的字符串更新。

下面的例子:

文件 1:

1047    510 75  Live
1048    510 75  Live
1049    510 75  Live
1627    510 75  Live
1628    510 75  Live
1629    510 75  Live

文件 2:

1047    510 75  Live
1048    510 75  Live
1049    510 75  Live
107     510 39  Live
108     510 39  Live
109     510 39  Live
117     510 39  Live
118     510 39  Live
119     510 39  Live
1627    510 75  Live
1628    510 75  Live
1629    510 75  Live
17      510 75  Live

目标:文件 3

1047    510 75  Live
1048    510 75  Live
1049    510 75  Live
107     510 39  Test
108     510 39  Test
109     510 39  Test
117     510 39  Test
118     510 39  Test
119     510 39  Test
1627    510 75  Live
1628    510 75  Live
1629    510 75  Live
17      510 75  Test

【问题讨论】:

  • 如果上面的第二个文件中存在1047 510 39 Live,输出应该是什么?应该是来自 file1 的行,还是来自 file2 的行,还是两行或其他什么?
  • @Imran - 欢迎来到 SO!到目前为止,您尝试过做什么?如果您不说明自己为合并所做的尝试,您可能不会获得太多帮助。
  • 文件 1 和文件 2:每个文件的前 2 列作为主键,应该用于比较这两个文件。将文件 2 的记录与文件 1 进行比较。如果文件 1 中存在记录,则将文件 2 中的记录替换为文件 1 中找到的记录 如果文件 1 中未找到记录,则仅更新文件 2 中该记录的最后一列。我希望它很清楚。
  • 我试过awk,但是处理了几条记录就​​失败了。 awk 'FNR==NR{a[$1,$2]=$3;next} ($1,$2) in a{print $0, a[$1,$2]}'

标签: linux join awk


【解决方案1】:

两种方法。

使用comm获取并集和差异:

{
    # lines in common
    comm -12 <(sort file1) <(sort file2)
    # lines only in file2
    comm -13 <(sort file1) <(sort file2) | awk '{$NF="Test"} 1'
} > file3

或者,坚持使用 awk

awk '
    # read and store file1
    NR==FNR {f1[$0]; next} 
    # for file2 lines not in file1, alter the last field
    !($0 in f1) {$NF = "Test"} 
    # print each line
    1
' file1 file2 > file3

您可以通过column -t 管道输出来美化file3:

awk '...' file1 file2 | column -t > file3

【讨论】:

  • 嗨格伦。感谢您的回复。我的问题有点复杂。我有两个文件:文件 1 和文件 2 每个文件的前 2 列构成主键,应该用于比较这两个文件。将文件 2 的记录与文件 1 进行比较。如果文件 1 中存在记录,则将文件 2 中的记录替换为文件 1 中找到的记录 如果文件 1 中未找到记录,则仅更新文件 2 中该记录的最后一列。我希望它很清楚。
  • 请在问题中添加其他要求。
【解决方案2】:

这可能对你有用(GNU sed):

sed -r 's|^(\S+\s+\S+\s+).*|/^\1/s/.*/&/;t|;$a\s/\\S+$/Test/' file1 |
sed -rf - file2 >file3

这会从 file1 生成一个 sed 脚本,它将 file2 中与 file1 的前两个字段匹配的行替换为 file1 中匹配行的内容。那些不匹配的行用Test 更新不匹配行的最后一列。结果打印到file3。

【讨论】:

    猜你喜欢
    • 2012-10-11
    • 1970-01-01
    • 1970-01-01
    • 2016-08-12
    • 1970-01-01
    • 2014-10-23
    • 2018-10-17
    • 1970-01-01
    • 2016-11-21
    相关资源
    最近更新 更多