【问题标题】:Find common lines between two files and also their line number查找两个文件之间的公共行及其行号
【发布时间】:2013-12-20 13:07:34
【问题描述】:

我想找到两个文件(大文件)之间的公共行,一个有 9000 万行,1 个有 100000 行以及它们的行号。

comm -12 file1 file2

给了我常用的行,但我也想知道各个文件的行号

【问题讨论】:

  • 你的意思是10万行的那个已经有行号了?
  • 那么,如果一行出现在文件 1 的第 300 行和文件 2 的第 500 行,你期望得到什么输出?如果它在文件 2 的第 600 行再次出现怎么办?
  • @MarkSetchell 300 commonline 500

标签: bash shell


【解决方案1】:

此解决方案适用于我的小型测试文件 - 我不确定它在包含 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 这是一件好事,在问题上添加更多想法可能会很有趣,但是我希望您也考虑问题发布的时间,以及 OP 是否仍然关心他的问题所以也许你不会在上面浪费你的精力。干杯。
  • 我已经多次提到 XKCD。你有我的弓、我的斧头和我的赞成票。
【解决方案2】:

你可以试试:

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 ""
    }
}

【讨论】:

    【解决方案3】:

    您可以通过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 @@
    

    这意味着以 - 或 diff 中的空格开头的下一行是 file1 中的第 1 行,而以 + 或空格开头的下一行是 file2 中的第 2 行。为了您的目的,您可以忽略逗号后面的数字。

    【讨论】:

      猜你喜欢
      • 2021-08-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-20
      • 1970-01-01
      • 1970-01-01
      • 2013-06-25
      • 1970-01-01
      相关资源
      最近更新 更多