如何比较两个没有分隔符的文件的特定位置

如何比较两个没有分隔符的文件的特定位置

我需要逐行比较两个文件。我只想输出那些不同的行,但在确定差异时,应忽略字符 4-6 和 10-12。没有特定的字段分隔符等。

例子:

  • 文件1
    abc123def999
    ghi456klm999
    nop789qrs999
    
  • 文件2
    abc000def000
    xxx000yyy000
    nop000qrs000
    

在该示例中,只有第二行应该不同。

我不希望read循环逐行解析文件,因为文件有数百万条记录。

答案1

使用 GNU awk 作为 FIELDWIDTHS 参数:

$ paste file[12] |
    awk -v FIELDWIDTHS='3 3 3 3 1 3 3 3 3' '$1!=$6 || $3!=$8'
ghi456klm999    xxx000yyy000

这里我们使用paste命令并排粘贴两个文件;然后假设两个文件中的行都是固定长度,因为我们使用 awk 的 FIELDWIDTHS 参数来定义字段长度,然后我们比较相关字段的差异;这里的比较是逐行进行的。

或者在任何 shell 中使用任何 awk:

$ paste file[12] |
    awk 'function key(s){return substr(s,1,3) substr(s,7,3)} key($1) != key($2)'
ghi456klm999    xxx000yyy000

答案2

您没有显示预期的输出,也没有真正告诉我们您的要求是什么,所以这里是您可能想要的一种猜测,在每个 Unix 机器上的任何 shell 中使用任何 awk:

$ cat tst.awk
{ key = substr($0,1,3) substr($0,7,3) }
NR == FNR {
    a[key]
    next
}
!(key in a)

$ awk -f tst.awk file1 file2
xxx000yyy000

$ awk -f tst.awk file2 file1
ghi456klm999

答案3

两个文件都有“数百万条记录”?选择较短的文件,读取每一行,生成一个以“ ^”(行开头)开头、以“ $”(行结尾)结尾的正则表达式,搜索字符串位于其间。将要忽略的位置设置为“ .”(正则表达式“匹配任何单个字符”)。例如“ ^abc...def...$”。将其保存在临时文件中 ( file1.tmp)(数百万?)。当您处理完所有行后,将在ingrep -E -f file1.tmp file2中搜索正则表达式。file1.tmpfile2

答案4

方法-1)perl

unpack函数最适合这种情况,根据 perl 环境托盘上提供的格式提取特定的字符范围。(A3x3)2A*=> 选择三个 ASCII 字符,然后跳过三个字符。再次重复这个过程,然后抓住剩下的东西。

fmt='(A3x3)2A*' \
perl -nse 'print if "@{[unpack($ENV{fmt})]}" ne
"@{[unpack($ENV{fmt},scalar(<STDIN>))]}";
' -- -\"= File1 < File2
ghi456klm999

方法-2)paste+GNU sed

粘贴将两个文件中的相应行并排放置并用制表符分隔。因此,我们假设文件中不应有选项卡。然后我们将两个文件的数据中的 4-6、10-12 个字符替换为相同的字符“.”。在比较线路之前。当 Ines 不匹配时,打印 file1 行。

# helper vars aid in writing sed code
x3='...'
A3="($x3)"
A3x3=$A3$x3
srch="^$A3x3$A3x3"
repl="\\1$x3\\2$x3"

paste File1 File2 |
sed -En 'y/\t/\n/;h
  '"s/$srch/$repl/Mg"'
  /^(.*)\n\1$/d;g;P
' -

方法-3)Python

内置 zip 函数会并排查看两个文件的行。

python3 -c 'import sys
# skip chars: 4-6 10-12
AoT = [(0,3),(6,9),(12,None)] # array of tuples

fx = lambda t: \
  a[t[0]:t[1]] != b[t[0]:t[1]]

ifile1,ifile2 = sys.argv[1:]
with open(ifile1) as f1,\
     open(ifile2) as f2:
  for a,b in zip(f1,f2):
    if any(map(fx,AoT)):
      print(a,end="")
' File1 File2

相关内容