【问题标题】:perl script to find fields matching in two filesperl 脚本查找两个文件中匹配的字段
【发布时间】:2015-09-20 04:09:27
【问题描述】:

我有两个文件,想从两个文件中找到匹配的字段 1 和 2,并在字段 1 和 2 匹配时从第二个文件中打印第三个字段。文件 1 看起来像:

#CHR BP                                                                                                          
#1 9690639                                                                                                      
#1 7338706                                                                                                      
#1 7338707                                                                                                      
#1 7338717

文件 2 看起来像:

#1 10036 rs11928874 CT C 315.21 VQSRTrancheINDEL99.99to100.00AC=3;AF=0.063;AN=48;BaseQRankSum=0.297;DP=1469;FS=16.265;InbreedingCoeff=-0.0941;MLEAC=3;MLEAF=0.063;MQ=14.67;MQ0=0;MQRankSum=1.339

我编写了以下 perl 脚本,它输出了太多不符合匹配条件的行:

my @loci;
open IN, "highalt_results.txt";
while (<IN>) {
    my @L = split;
    next if m/CHR/;
    push @loci, [ $L[0], $L[1] ];
}
close IN;

my $F = shift @ARGV;
open IN, "$F";
while (<IN>) {
    my @L = split;
    next if m/#CHROM/;
    foreach (@loci) {
        if ( $L[0] = ${$_}[0] ) {
            if ( $L[1] = ${$_}[1] ) {
                print "${$_}[0] ${$_}[1] $L[2]\n";
                next;
            }
        }
    }
}

谁能指出脚本哪里出错了?

【问题讨论】:

标签: regex perl


【解决方案1】:

我认为这将是您的错误所在:

    if ( $L[0] = ${$_}[0] ) {
        if ( $L[1] = ${$_}[1] ) {

Equals 是一个赋值 - 所以永远是正确的。你可能想要==。或者eq 用于基于字符串的比较。

更一般地说——我认为你应该做几件事来收紧你的代码。

  • strictwarnings 真的很好。
  • 3 个参数open 与词法文件句柄很好open ( my $input, "&lt;", $filename ) or die $!; - 这避免了@ARGV 上指定的文件名的潜在问题。 (考虑一个名为 '&gt;/etc/passwd' 的文件)
  • 你真的应该检查open 是否成功。
  • 我可能会建议不要在你的 foreach 循环中使用隐含变量,因为${$_}[0] 不是特别好。使用-&gt; 取消引用可以使代码更好。

我可能会重写为:

use strict;
use warnings;

my @loci;
open( my $loci_in, "<", "highalt_results.txt" ) or die $!;
while (<$loci_in>) {
    my ( $start, $end ) = split;
    next if m/CHR/;
    push @loci, [ $start, $end ];
}
close $loci_in;

my $filename = shift @ARGV;
open( my $input, "<", $filename ) or die $!;
while (<$input>) {
    next if m/#CHROM/;
    my ( $start, $end, $data ) = split;
    foreach my $pair (@loci) {
        if (    $start == $pair->[0]
            and $end == $pair->[1] )
        {
            print "$start $end $data\n";

        }
    }
}
close($input);

【讨论】:

    【解决方案2】:

    至少你有错误 如果($L[0] = ${$}[0]){ if ( $L[1] = ${$}[1] ) {

    您应该使用 == 或 -eq 进行比较

    请清除您的数据文件格式。我看不到匹配的字段

    【讨论】:

      猜你喜欢
      • 2015-04-04
      • 2016-11-23
      • 2015-11-11
      • 2015-01-11
      • 1970-01-01
      • 2015-08-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多