【问题标题】:extract first entry from a file based on its corresponding ID list in second file?根据第二个文件中对应的 ID 列表从文件中提取第一个条目?
【发布时间】:2018-08-09 21:21:52
【问题描述】:

我有一个 2 文本文件。 file1 包含 ID:

0   ABCD  
3   ABDF
4   ACGFR
6   ABCD
7   GFHTRSFS

file2

ID001  AB  ACGFR  DF  FD  GF  TYFJ  ANH  
ID002  DFR  AG  ABDF  HGT  MNJ  POI  YUI
ID003  DGT  JHY  ABCD  YTRE  NHYT  PPOOI  IUYNB
ID004  GFHTRSFS  MJU  UHY  IUJ  POL  KUH  KOOL

如果文件 1 的第二列与文件 2 中的任何条目匹配,则文件 2 的第一列应该是它的答案。

输出应该是这样的:

0   ID003
3   ID002
4   ID001
6   ID003
7   ID004

(文件 1 (ABCD) 的第 2 列与文件 2 的第 3 行匹配,其中 ID003。因此,ID003 应该是它的答案)。

我也尝试过其他帖子中的示例,但不知何故,它们与此不匹配。

任何帮助将不胜感激。

亲切的问候

【问题讨论】:

  • StackOverflow 希望你能try to solve your own problem first。请更新您的问题以在minimal reproducible example 中显示您已经尝试过的内容。如需更多信息,请参阅How to Ask,并拨打tour :)
  • @Barmar 和@Matt。我是脚本的新手。尽管我在 libre office-calc 上花了几个小时来解决这个问题。但它没有按我的方式进行。所以最后我不得不在这里发布。
  • @Parthpatel 在此处发帖很好,但您需要遵守规则。既然你问的是关于代码的问题,那么代码在哪里?
  • 检查Related下的问题,例如stackoverflow.com/questions/18471084/…。然后展示你的努力和你卡在哪里

标签: linux perl unix awk


【解决方案1】:

当尝试将一个文件中的记录与另一个文件中的记录进行匹配时,想法是使用hash ( also known as an associative array, set of key-value pairs, or dictionaries ) 来存储第一列与其余列之间的关系。实际上,创建以下关系:

file1: ABCD     -> 0
       ABDF     -> 3
       ACGFR    -> 4
       FGHTRSS  -> 6
       GFHTRSFS -> 7

file2: AB    -> ID001
       ACGFR -> ID001
       DF    -> ID001
       ...
       ANH   -> ID001
       DFR   -> ID002
       AG    -> ID002
       ...
       KUH   -> ID004
       KOOL  -> ID004

文件之间记录的实际匹配相当于确定 如果两个散列,这里 file1 和 file2 都有为每个 file1 记录定义的键。在这里我们可以看到ACGFR 是两者的键,因此我们可以匹配4ID001,以此类推其余键。

在 perl 中,我们可以通过分配成对的值来创建哈希:

my %hash = ( foo => 1, bar => 2 );

也可以使用引用创建哈希:

my $hash_ref = { foo => 1, bar => 2 };

可以使用keys 函数找到键,并且可以提取单个值:

my $val1 = $hash{ foo };       # regular hash
my $val2 = $hash_ref->{ foo }; # hash reference

可以使用exists 函数测试特定键是否是哈希的成员。

在不影响该背景的情况下,这是在 perl 中执行此操作的一种方法:

ma​​tchup_files.pl

#!/usr/bin/env perl

use warnings;
use strict;

my $usage = "usage: $0 file1 file2\n";

my ($file1, $file2) = @ARGV;
for my $file ($file1, $file2) {
    die $usage unless defined $file && -f $file; # -f checks whether $file is an actual file
}

# Create mappings col2 -> col1
#                 col3 -> col1
#                 col4 -> col1
my $h1 = inverted_hash_file_on_first_column( $file1 );
my $h2 = hash_file_on_first_column( $file2 );

# Try to find matching pairs
my $matches = {};
for my $h1_key ( keys %$h1 ) {
    my $h1_val = $h1->{$h1_key};
    if ( exists $h2->{ $h1_val } ) {
        # We have a match!
        my $num = $h1_key;
        my $id  = $h2->{ $h1_val };
        $matches->{ $num } = $id;
    }
}

# Print them out in numerical order
for my $num ( sort { $a <=> $b } keys %$matches ) {
    my $id = $matches->{$num};
    print join("  ", $num, $id) . "\n";
}

exit 0; # Success

sub inverted_hash_file_on_first_column {
    my ($file) = @_;
    return _hash_file($file, 1);
}

sub hash_file_on_first_column {
    my ($file) = @_;
    return _hash_file($file, 0);
}

sub _hash_file {
    my ($file, $inverted) = @_;

    my $fhash = {};
    open my $fh, "<", $file or die "Unable to open $file : $!";
    while ( my $line = <$fh> ) {
        my @fields = split /\s+/, $line; # Split line on whitespace
        my $key = shift @fields; # First column
        for my $field ( @fields ) {
            if ( $inverted ) {
                die "Duplicated field '$field'" if exists $fhash->{ $key };                
                $fhash->{ $key } = $field;
            } else {
                die "Duplicated field '$field'" if exists $fhash->{ $field };
                $fhash->{ $field } = $key;
            }
        }
    }
    return $fhash;
}

输出

matchup_files.pl input1 input2
0  ID003
3  ID002
4  ID001
6  ID003
7  ID004

【讨论】:

  • 你好@xxfelixxx,谢谢你的帮助。但是,如果我在第二个文件中有多个列要查找,这个 perl 脚本是否可以工作?因为文件 2 有多个列(任何列都可以有一个我正在寻找的 ID)。问候
  • 它会检查除第一列之外的每一列是否可能匹配,所以是的,它应该可以工作,试试看!
  • 应该可以,但请原谅我。当我运行命令时。它以错误告终。 “hi.perl 第 46 行, 第 11 行的重复字段 '12'”...你能告诉我这是什么意思吗?...亲切的问候
  • 我应该在前面提到,我的文件可以在文件 1 的第一列中包含重复值(我在第二个文件中搜索的 ID).. 有什么办法可以解决这个问题?跨度>
  • 当然可以,但是您需要决定如何处理这种情况,如果第一场比赛获胜,最低/最高 id 应该获胜,还是其他?等等
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
  • 2016-12-29
  • 1970-01-01
  • 1970-01-01
  • 2018-09-15
相关资源
最近更新 更多