我想找到两个文件(大文件)之间的公共线,一个有9千万行,1个有10万个,还有它们的行号。
comm -12 file1 file2
给了我常用的行,但我想知道单个文件中的行号
答案 0 :(得分:2)
此解决方案适用于我的小型测试文件 - 我不确定它将如何在包含9000万行的文件上执行。
tab=` printf '\t' `
join -t"$tab" -j2 <( cat -n file1 ) <( cat -n file2 )
这是有效的,因为cat -n
会在每行前面添加一个空格填充的数字后跟一个制表符。然后join
找到公共线,只查看第一个标签后的内容。
连接完成后,您应该看到公共线,每条线后跟两个数字。第一个数字是file1的行号,第二个是file2。
警告:如果文件中没有制表符,这将有效。如果不是这种情况,您可以使用sed将第一个标签转换为“安全”字符。
safe="|"
join -t"$safe" -j2 \
<( cat -n file1 | sed -e "s:\t:$safe:" ) \
<( cat -n file2 | sed -e "s:\t:$safe:" )
此外,根据join
的实现方式,您可能希望在第一个进程替换中列出较小的文件,在第二个进程替换中列出较大的文件。这样,较小的文件可以全部适合存储器,并且可以扫描较大的文件并有效地选择匹配的行。我不知道是不是这样,但它可能值得一试。
答案 1 :(得分:0)
您可以尝试:
awk '
FNR==NR {
a[$0]++
next
}
$0 in a {
print
delete a[$0]
}' file1 file2
如果您还想获取行号,可以使用gawk版本4中的数组数组,如:
FNR==NR {
a[$0][FNR]++
file1=FILENAME
next
}
FNR==1 {
file2=FILENAME
}
$0 in a {
b[$0][FNR]++
}
END {
for(i in b) {
print "Line: " i
print " Line numbers in "file1":"
printf " "
for (j in a[i])
printf "%s,", j
print ""
print " Line numbers in "file2":"
printf " "
for (j in b[i])
printf "%s,", j
print ""
}
}
答案 2 :(得分:0)
你可以用diff
到达那里。这会显示file1
中的行号,但不幸的是,似乎没有任何选项显示来自file2
的行号 - 似乎man diff
假设未更改的行也是在两个文件中的相同的行,这与它通常的工作方式相反。
diff --unchanged-line-format=$'%dn\t%L' --old-line-format='' --new-line-format='' file1 file2
使用unified diff的另一半措施:
diff -u file1 file2
这显示了带有一些上下文的不同的行,这意味着您可以推断公共文本所在的行。以@@
开头的行为您提供行信息。例如:
@@ -1,5 +2,10 @@
这意味着以-
开头的下一行或差异中的空格是file1
中的第1行,而下一行以+
开头或空格是第2行file2
。为了您的目的,您可以忽略逗号后面的数字。