【问题标题】:Compare two files using first column, print diff while appending column to output使用第一列比较两个文件,在将列附加到输出时打印差异
【发布时间】:2022-01-23 00:42:14
【问题描述】:

我有两个要比较的制表符分隔文件。

我想查找 file1 中 col1 在 file2 中丢失的值(以“left”开头)和 file2 中 col1 中在 file1 中缺失的值(以“joined”开头)。对于这些行,我想打印 col1 和 col8。对于 col1 相同且 col8 值不同的行,我的 diff 命令失败。

文件1:

Char1   55  Necromancer Knight  A   11/21/21    Zone    Char1(Main)     off off 0       Char1(Main) 
Char2   28  Druid   Squire  A   12/08/21    Zone    Char1       off off 0       Char1   
Char3   44  Enchanter   Recruit A   08/07/21    Zone    Char3(Main)     off off 0       Char3(Main) 
Char4   56  Enchanter   Knight  A   11/06/21    Zone    Char4(Main)     off off 0       Char4(Main) 
Char5   10  Magician    Recruit A   10/29/21    Zone    Char1       off off 0       Char1   
Char6   65  Druid   Champion    A   12/12/21    The Lair of the Splitpaw    Char6(Main) VT emp time     off off 0       Char6(Main) VT emp time 

文件2:

Char1   55  Necromancer Knight  A   11/21/21    Zone    Char1(Main)     off off 0       Char1(Main) 
Char2   28  Druid   Squire  A   12/08/21    Zone    Char1       off off 0       Char1   
Char3   44  Enchanter   Recruit A   08/07/21    Zone    Char3(Main)     off off 0       Char3(Main) 
Char4   56  Enchanter   Knight  A   11/06/21    Zone    Char4(Main)     off off 0       Char4(Main) 
Char5a  10  Magician    Recruit A   10/29/21    Zone    Char1       off off 0       Char1   
Char6   65  Druid   Champion    A   12/21/21    Zone    Char6(Main) Emp/VT/Time     off off 0       Char6(Main) Emp/VT/Time 

diff 命令产生输出:

diff --new-line-format="joined %L" --old-line-format="left %L" --unchanged-line-format="" <(cut -f1,8 "$file1" | sort) <(cut -f1,8 "$file2" | sort) | sort

当前输出:

joined Char5a   Char1
joined Char6    Char6(Main) Emp/VT/Time
left Char5      Char1
left Char6      Char6(Main) VT emp time

期望的输出:

joined Char5a   Char1
left Char5      Char1

非常感谢任何帮助,谢谢!

【问题讨论】:

  • 有什么问题吗?电流输出错了吗?当前输出是否需要以不同的格式显示?请使用 2 个示例输入文件更新问题,仅执行所需处理所需的代码(例如,我们真的需要知道您如何找到要处理的 2 个文件吗?),您的代码生成的(错误)输出和(正确的)预期输出
  • 我认为在运行函数的最后两行中“问题”很清楚。当我不希望它这样做但仍希望它打印时,它会检测到第二列的更改。
  • @Jedis 在阅读了你的问题几次之后,我想我明白了。将问题完全弄清楚总是很困难的,因此拥有两个各有 2 列和 6 行的输入文件以及您想要的结果会有所帮助。也许改写您的问题,例如`我想查找file2中缺少的file1中col1的值(以“left”开头)和file1中缺少的file2中col1中的值。对于这些行,我想打印 col1 和 col8。对于 col1 相同且 col8 值不同的行,我的 diff 命令失败。
  • @WalterA 谢谢。我已经编辑了我的帖子以重新措辞并使其更加清晰。

标签: bash unix awk diff


【解决方案1】:

Diff 用于简单的差异。使用awk 可以更轻松地解决您的问题。
您不需要对文件进行排序,只需读取两个文件并计算第 1 列中的键出现的频率。
在计算关键值的同时准备潜在的输出。当NR==FNR 您在第一个文件中并且您想使用“left”时。
读取两个文件后,查找仅出现一次的键并打印为该行准备好的输出。

awk -F'\t' '
  {
    key[$1]++
    value[$1]=(NR==FNR ? "left " : "joined ") $1 "\t" $8
  }
  END { 
    for (i in key) { 
      if (key[i]==1) { 
        print value[i]
      }
    }
  }' file1 file2

【讨论】:

  • 谢谢。我必须添加 -F'\t' 来告诉它我正在使用制表符分隔的文件,否则它会抛出奇怪的、不一致的输出,其中的列和某些行在每一列中都没有数据。将继续对其进行更多测试。
  • 我加了-F'\t',大家可以看看stackoverflow.com/help/someone-answers
【解决方案2】:

希望这个 python 脚本能得到你所期望的:

#!/bin/bash

python -c '
import re, sys
def read_into_dict(regex, file):
    return { re.findall(regex, line)[0]: line for line in open(file) }
regex, file1, file2 = sys.argv[1:]
dict1 = read_into_dict(regex, file1)
dict2 = read_into_dict(regex, file2)
keys1 = set(dict1.keys())
keys2 = set(dict2.keys())
for key in (keys1 - keys2):
    print(f"left {dict1[key]}")
for key in (keys2 - keys1):
    print(f"joined {dict2[key]}")
' '^(\S+)' <(cut -f1,8 "$file1" | sort) <(cut -f1,8 "$file2" | sort) | sort

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-25
    • 2013-04-25
    • 2013-06-17
    • 2016-12-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多