【问题标题】:How to compare two files and print second file only matching the first file如何比较两个文件并打印仅匹配第一个文件的第二个文件
【发布时间】:2013-11-22 22:10:57
【问题描述】:

我有两个文件。一个有两列,ref.txt。另一个有三列,file.txt。

在 ref.txt 中,

1  2
2  3
3  5

在file.txt中,

1  2  4   <---here matching
3  4  5
6  9  4
2  3  10  <---here matching
4  7  9
3  5  7   <---here matching

我想比较每个文件的两列,然后只打印 file.txt 中与 ref.txt 匹配的行。

所以,输出应该是,

1  2  4
2  3  10
3  5  7

我认为两个字典比较之类的,

mydict = {}
mydict1 = {}

with open('ref.txt') as f1:
     for line in f1:
         key, key1 = line.split()
         sp1 = mydict[key, key1]

with open('file.txt') as f2:
      for lines in f2:
          item1, item2, value = lines.split()
          sp2 = mydict1[item1, item2]
          if sp1 == sp2:
             print value

如何将两个文件与字典或其他文件进行适当的比较?

我找到了一些 perl 和 python 代码来解决两个文件中相同数量的列。

在我的例子中,一个文件有两列,另一个有三列。

如何比较两个文件,只打印匹配的值?

【问题讨论】:

  • 类似for i in (ref.txt) do grep "^$i" file.txt; done 的东西会接近。
  • file.txt 中的条目 0 1 2 是否被视为匹配项?基本上,ref.txt 中的条目必须在 file.txt 行的任何位置找到,还是必须在 start with 行的值?
  • 这里有一个类似的问题:stackoverflow.com/q/17490570/1967396 - 它想在某些列上匹配(但在这种情况下这些列被混淆了 - 比你的问题更难)。答案很有趣,值得一读。
  • 感谢所有cmets。

标签: python perl comparison


【解决方案1】:

这是另一个选择:

use strict;
use warnings;

my $file = pop;
my %hash = map { chomp; $_ => 1 } <>;

push @ARGV, $file;

while (<>) {
    print if /^(\d+\s+\d+)/ and $hash{$1};
}

用法:perl script.pl ref.txt file.txt [&gt;outFile]

最后一个可选参数将输出定向到文件。

数据集的输出:

1  2  4
2  3  10
3  5  7

希望这会有所帮助!

【讨论】:

  • 你是怎么得到这个输出的?这段代码在我运行时也有错误。在 ref.txt 第 1 行,“1 2”附近的运算符预期位置找到编号(2 之前缺少运算符?)在 ref.txt 第 2 行,“2”附近的运算符预期位置找到编号(前一行缺少分号?)找到的编号where 操作符在 ref.txt 第 2 行,靠近“2 3”(在 3 之前缺少操作符?)在 ref.txt 第 3 行,在“3”附近找到操作符(上一行缺少分号?)在 ref 处出现语法错误.txt 第 1 行,“1 2”附近 ref.txt 的执行由于编译错误而中止。
  • @ChangWoonJang - 我很抱歉。我最初的用法是perl ref.txt file.txt [&gt;outFile],但它应该是perl script.pl ref.txt file.txt [&gt;outFile],现在已修复。是的!仅仅将这两个文本文件直接发送到 Perl 是行不通的。
  • 我们如何使用 Python 做到这一点?我对 Perl 一无所知。
【解决方案2】:
grep -Ff ref.txt file.txt
如果两个文件中字符之间的空格量相同,则

就足够了。如果不是,你可以这样做

awk '{print "^" $1 "[[:space:]]+" $2}' | xargs -I {} grep -E {} file.txt

结合我最喜欢的三个实用程序:awkgrepxargs... 后一种方法还确保匹配只发生在行首(比较第 1 列和第 1 列,以及第 2 列与第 2 列)。

【讨论】:

  • 第一个 grep 很简单,可以正常工作。非常感谢。
  • "让事情尽可能简单,但不要更简单。" - 通常归功于阿尔伯特·爱因斯坦。
  • "grep command" 有两个小问题。如果 file.txt 包含 111 2 4,这也与 ref.txt 中的 1 2 匹配,因为 111 和 2 中的最后一个 1 匹配 ref.txt 中的 '1 2'。此外,如果双空格与数字之间的单空格不是相同的模式。这是一种简单而好的方法,但需要改进。非常感谢。
  • 这就是我给出第二个例子的原因 - 正是为了解决这些问题。它只会匹配“从一开始”(使用^)和可变数量的空间(使用[[:space:]])。不幸的是,它使它变得更加复杂 - 但仍然适合单行。
【解决方案3】:

这是一个经过修改和注释的版本,应该适用于您的更大数据集:

#read in your reference and the file
reference = open("ref.txt").read()
filetext = open("file.txt").read()

#split the reference file into a list of strings, splitting each time you encounter a new line
splitReference = reference.split("\n")

#do the same for the file
splitFile = filetext.split("\n")

#then, for each line in the reference,
for referenceLine in splitReference:

  #split that line into a list of strings, splitting each time you encouter a stretch of whitespace
  referenceCells = referenceLine.split()

  #then, for each line in your 'file',  
  for fileLine in splitFile:

    #split that line into a list of strings, splitting each time you encouter a stretch of whitespace
    lineCells = fileLine.split()

    #now, for each line in 'reference' check to see if the first value is equal to the first value of the current line in 'file'
    if referenceCells[0] == lineCells[0]:

      #if those are equal, then check to see if the current rows of the reference and the file both have a length of more than one
      if len(referenceCells) > 1:
        if len(lineCells) > 1:

          #if both have a length of more than one, compare the values in their second columns. If they are equal, print the file line
          if referenceCells[1] == lineCells[1]:
            print fileLine

输出:

1  2  4
2  3  10
3  5  7

【讨论】:

  • 我对这段代码有一个错误,例如 Traceback (最近一次调用最后一次): File "test.py", line 13, in if referenceCells[0] == lineCells[0] : IndexError: list index out of range 你是怎么得到这个输出的?谢谢。
  • 我猜对了,您在生成此错误消息时使用的输入文件包含的行数比您在此处提供的示例数据多吗?较大的文件中必须有一行或多行包含空单元格。我将编辑我的答案,向您展示如何处理这些行...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-01
  • 2020-08-20
  • 2014-07-06
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多