如何从两个文件中获取行中的退休和新增内容?
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 循环中丢弃
问题:
我有 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 循环中丢弃