比较 2 个文件中的每第 n 行并保存(非对称)上下文

比较 2 个文件中的每第 n 行并保存(非对称)上下文

我有 2 个文件,每个文件包含相同数量的 4 行记录,且顺序相同:

fileA:

record1 line1=header
record1 line2 X <= this is different but should be ignored
record1 line3 id ABC
record1 line4
record2 line1=header
record2 line2
record2 line3 id DEF <= this is different
record2 line4

fileB:

record1 line1=header
record1 line2 Y <= this is different but should be ignored
record1 line3 id ABC
record1 line4
record2 line1=header
record2 line2
record2 line3 id GHI <= this is different
record2 line4

对于每条记录,我想比较line3两个文件之间的情况,如果line3不同,则保存 fileB 的整个记录​​(第 1-4 行);在上面的示例中,record1 将被忽略并保存 record2。我有基本知识,diff但不确定它是否可行。首先,我不知道如何只比较每第三行并忽略其他行;第二,-C定义对称的上下文,即差异之前和之后的行数相同......

UPD。最初,我在示例中犯了一个错误:记录之间有空行,而我的真实文件中没有该空行。我对此表示歉意。根据@stteldriver的回答,我有以下解决方案:

awk '
NR%4==3 {
lineA3=$0; 
getline lineB1 < "fileB"; 
getline lineB2 < "fileB"; 
getline lineB3 < "fileB"; 
getline lineB4 < "fileB";  
if (lineA3 != lineB3) {printf "%s\n%s\n%s\n%s\n", lineB1,lineB2,lineB3,lineB4;}
}' fileA

它工作完美!虽然代码相当丑陋(我才刚刚开始学习awk!),如果您能优化它,我将不胜感激。

答案1

对于更新的输入,严格基于 4 行记录,您可以使用模算术来维护当前记录的数组,并每隔 4 行检查第 3 行是否匹配:

$ awk '
    {a[FNR%4] = $0; getline b[FNR%4] < "fileB"} 
    !(FNR%4) && b[3] != a[3] {
      for(i=0;i<4;i++) print b[i%4]
    }
  ' fileA
record2 line1=header
record2 line2
record2 line3 id GHI <= this is different
record2 line4

(请注意,确实应该检查命令的返回值getline,并在失败时执行一些明智的操作)。


对于您最初发布的输入,您可以使用段落模式:

$ awk -vRS= -F'\n' '{A3 = $3}; getline "fileB" > -1 && $3 != A3' fileA
record2 line1=header
record2 line2
record2 line3 id DEF <= this is different
record2 line4

对于正常处理(来自 的输入)和(来自 的输入),空RS会导致读取整个空行分隔的记录。将字段分隔符设置为换行符 ( ) 然后允许我们保存其中的整行并与另一行进行比较。如果它们不相等,则默认打印输出(这是of 的整个记录​​)。fileAgetlinefileB\n$3$0getlinefileB

答案2

这是一个可以执行您想要的操作的 Python 脚本:

#!/usr/bin/env python3
# -*- encoding: utf-8 -*-
"""compare.py"""

import sys

file_A = open(sys.argv[1], "r")
file_B = open(sys.argv[2], "r")

records_A = file_A.read().split("\n\n")
records_B = file_B.read().split("\n\n")

for record_A, record_B in zip(records_A, records_B):
    lines_A = record_A.split("\n")
    lines_B = record_B.split("\n")
    if lines_A[2] != lines_B[2]:
        print("{}\n".format(record_B))

你可以像这样运行它:

python compare.py fileA fileB

当我在示例数据上运行它时,我得到了所需的输出:

record2 line1=header
record2 line2
record2 line3 id GHI <= this is different
record2 line4

相关内容