以下是我正在编写的模块的玩具版本。这个例子忠实地展示了我遇到的问题。
我有一个文件bed_in.txt
2L 0 4953
2L 16204 16284
2L 16612 16805
2L 17086 18561
2L 18757 18758
2L 19040 19120
2L 19445 19635
2L 19894 21366
2L 21582 21583
2L 47501 52365
2L 4698700 4709369
我想用来过滤数组中的值。
我想检查bed_in.txt
的第二列是否与
my @lines = qw/ 16204 40 200 149 19445 178 /;
如果是这样,将此推送到数组。
此数据的最终输出应该是@lines
中同样位于bed_in.txt
2L 0 4953
2L 16204 16284 # 16204 == 16204
2L 16612 16805
2L 17086 18561
2L 18757 18758
2L 19040 19120
2L 19445 19635 # 19445 == 19445
但我应该在哪里打开文件?
是否应该在调用模块run_fileOpen.pl
的脚本中或模块本身中发生这种情况?
在任何一种情况下,我都没有得到正确的输出,我的模块似乎只被调用@lines
的第一个元素
#!/usr/bin/perl
package parseFile;
use strict;
use warnings;
use FindBin qw/ $Bin /;
use lib File::Spec->catdir($FindBin::Bin, '..', 'bin/');
use Data::Printer;
open my $bed, '<', 'bed_in.txt';
sub check_lines {
my ($line, $filter_ref) = @_;
my @filter_reasons = @{ $filter_ref };
my $lines_to_filter_ref = filter_lines($line, $bed, \@filter_reasons);
return($lines_to_filter_ref);
}
sub filter_lines {
my ($line, $bed_file, $lines_to_filter) = @_;
my @filter = @{ $lines_to_filter };
while(<$bed_file>){
chomp;
my $start = (split)[1];
# print "line: $line start: $start\n";
if ($line == $start ) {
push @filter, "Filter as equal: $start, $line [$_]";
}
}
# p(@filter);
return(\@filter);
}
1;
#!/usr/bin/perl
use strict;
use warnings;
use parseFile;
my @lines = qw/ 16204 40 200 149 19445 178 /;
foreach(@lines){
my @filter_reasons = 'reason 1';
my $lines2filter = parseFile::check_lines($_, \@filter_reasons);
@filter_reasons = @{ $lines2filter };
print "$_\n" foreach @filter_reasons;
}
reason 1
Filter as equal: 16204, 16204 [2L 16204 16284]
reason 1
reason 1
reason 1
reason 1
reason 1
当我向print
中的while
循环添加filter_lines
语句时,我可以看到只有第一个元素正在运行:
line: 16204 start: 0
line: 16204 start: 16204
line: 16204 start: 16612
line: 16204 start: 17086
line: 16204 start: 18757
line: 16204 start: 19040
line: 16204 start: 19445
line: 16204 start: 19894
line: 16204 start: 21582
line: 16204 start: 47501
line: 16204 start: 4698700
这是处理打开bed_in.txt
文件的合适方式,还是应该在run_parseFile.pl
脚本中打开它?或者我的代码还有其他问题吗?
答案 0 :(得分:1)
以下是我写这个的方法。正如我所说,我更喜欢面向对象的解决方案
new
构造函数需要文件名作为参数。它打开文件,将信息读入哈希,并祝福制作对象
唯一的方法是check_lines
,它需要一个值和一个原因字符串。它只是询问给定值的哈希值,并根据值是否找到返回一个或两个元素的数组
最好限制此对象的范围,否则哈希将在需要后保留在内存中。所以我已经将所有需要该对象的操作包含在一个块中。当对象在块结束时超出范围时,它将被自动销毁
package BedInFilter;
use strict;
use warnings 'all';
use Carp 'croak';
sub new {
my $class = shift;
my ( $bed_file ) = @_;
my %self;
open my $fh, '<', $bed_file
or croak qq{Unable to open "$bed_file" for input: $!};
while ( <$fh> ) {
next unless /\S/;
chomp;
my $val = ( split )[1];
$self{$val} = $_;
}
bless \%self, $class;
}
sub check_lines {
my $self = shift;
my ( $val, $reason ) = @_;
my $result = [ $reason ];
my $line = $self->{$val};
push @$result, "Filter as equal: $val, $val [$line]" if $line;
$result;
}
1;
use strict;
use warnings 'all';
use BedInFilter;
my @values = qw/ 16204 40 200 149 19445 178 /;
{
my $filter = BedInFilter->new( 'bed_in.txt' );
for my $val ( @values ) {
my $reason = 'reason1';
my $result = $filter->check_lines( $val, $reason );
print "@$result\n";
}
}
reason1 Filter as equal: 16204, 16204 [2L 16204 16284]
reason1
reason1
reason1
reason1 Filter as equal: 19445, 19445 [2L 19445 19635]
reason1
答案 1 :(得分:0)
模块应该打开和关闭同一子程序中的文件,除非子的名称中有“open”,在这种情况下,它应该返回一个文件句柄作为其返回值之一。并且应该有一个相应的“关闭”子匹配每个“开放”子。