如何从两个文件中获取行中的退休和新增内容?

How to get retiring and new additions in lines from two files?

问题:

我有 2 个文件将根据一些在线提要每天更新,文件包含喜欢和输入,每天都会添加一些新行,一些会被删除。此外,每天文件中的行顺序 change.So 我想提取今天添加的行,还想知道昨天删除了多少行?

我遵循的方法:

假设有 3 个文件 2017-07-17.txt , 2017-07-18.txt and 2017-07-19.txt 个文件,数据如下。

2017-07-17.txt

a
b
c

2017-07-18.txt

a
b
d
e
f

2017-07-19.txt

f
e
a
c
b
d
g

对前两个文件进行了比较。

3d2
< c
4a4,5
> e
> f

从输出中很容易提取数据并知道删除了什么和添加了什么。但是我每天的输入范围是 100k 到 200k 行数据,所以使用 diff 是行不通的。

我在这种方法中遇到的问题

当有一天说 2017-07-19.txt 输入改变了它的顺序时,diff 逻辑在逐行扫描时非常有线地工作。

$ diff 2017-07-18.txt 2017-07-19.txt
0a1,2
> f
> e
1a4
> c
4,5c7
< e
< f
---
> g

是否有任何解决方案可用于获得这样的输出。

预期输出:

$ diff 2017-07-18.txt 2017-07-19.txt
    Addeed : c
             g

    Deleted : None

这应该可以做到。但请注意,此解决方案将导致您读取内存中的整个文件。

f1 = open("2017-07-18.txt")
f2 = open("2017-07-19.txt")

lines1 = set(f1.readlines())
lines2 = set(f2.readlines())

print lines2 - lines1 # added today

print lines1 - (lines2 & lines1) # deleted today  
findstr /v /x /L /g:filename1 filename2 |find /c /v ""

可能 计算两个文件之间的差异(不确定 200k 行会超出任何限制)

在 filename2 中找到 /v/x 完全匹配 /L 字面上 /g: 此文件中的行的行。将结果输出到 find,然后 /c 计算上一个命令中 /v 不匹配 "" 的行数(即计算上一个命令的行数)

要将其分配给变量,请使用

for /f %%a in ('findstr /v /x /L /g:filename1 filename2 ^|find /c /v "" ') do set count=%%a

(注意在竖线前插入的引号和插入符号)

在 awk 中:

$ awk '
NR==FNR{ a[]; next }              # hash first file contents to a
{
    if( in a)                     # if second file item is found in a
        delete a[]                # delete it
    else b[]                      # otherwise add it to b hash
}
END {                               # in the end
    print "Added:"
    for(i in b)                     # added are in b
        print i
    print "Deleted:"
    for(i in a)                     # deleted are in a
    print i
}' 2017-07-18.txt 2017-07-19.txt    # mind the order
Added:
c
g
Deleted:
$ cat awk-script
NR==FNR{a[[=10=]];next} 
{ 
  if([=10=] in a)
    a[[=10=]]=1
  else
    add=add"\t"[=10=]"\n"
} 
END {
  for(i in a)
    if(a[i]!=1)
      del=del"\t"i"\n"
  printf "Added:%s\n",(add)?add:"None\n"
  printf "Deleted:%s",(del)?del:"None\n"
}

$ awk -f awk-script 2017-07-18.txt 2017-07-19.txt
Added:  c
        g

Deleted:None
awk '
   # add and remove depending in wich file
   { A[] += (FNR==NR) * 2 - 1 } 

   END {
      # set in different category depending of count + create human list
      for( a in A){ T[A[a]] = T[A[a]] "\n  " a }

      # display result (thanks to @CWLiu very nice code)
      printf "Added: %s\n", (T[1]) ? T[1] : "None"
      printf "Deleted: %s\n", (T[-1]) ? T[-1] : "None"
      }
   ' 2017-07-19.txt 2017-07-18.txt

为了减少内存消耗,我们可以在第一部分达到 0 时删除 A[x] 元素,或者至少在 END 部分的 for 循环中丢弃