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

时间:2017-07-19 06:28:17

标签: shell batch-file awk diff

问题:

我有2个文件,每天会根据一些在线Feed进行更新,文件包含带输入的内容,每天会添加一些新行,有些会被删除。此外,每天文件中的行的顺序也会改变。所以我想提取今天添加的行,还想知道昨天删除了多少行?

我遵循的方法:

假设说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

5 个答案:

答案 0 :(得分:2)

$ cat awk-script
NR==FNR{a[$0];next} 
{ 
  if($0 in a)
    a[$0]=1
  else
    add=add"\t"$0"\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

答案 1 :(得分:1)

这应该这样做。但请注意,此解决方案将使您在内存中读取整个文件。

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  

答案 2 :(得分:1)

在awk中:

$ awk '
NR==FNR{ a[$1]; next }              # hash first file contents to a
{
    if($1 in a)                     # if second file item is found in a
        delete a[$1]                # delete it
    else b[$1]                      # 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:

答案 3 :(得分:0)

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

(注意引号和管道前插入的插入符号)

答案 4 :(得分:0)

awk '
   # add and remove depending in wich file
   { A[$1] += (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

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