逐行比较只返回每第二行
所以我想写一个脚本比较一个文件的每一行与其对应的文件2行(文件1的第1行与文件2的第1行,等等),以特定方式更改文件1的内容,然后返回此行。到目前为止编译的代码我是这样的:逐行比较只返回每第二行
#!/usr/bin/perl
# alleles.pl
use strict; use warnings;
use List::MoreUtils qw(uniq);
open my $AL, '<', shift or die $!;
open my $HMP, '<', shift or die $!;
<$AL>; # skip header
print scalar <$HMP>; # print header
while (<$AL>, <$HMP>) {
my @HMP_columns = split (/\t/, <$HMP>);
my @AL_columns = split (/\t/, <$AL>);
shift @AL_columns for 0..4;
my @uniq_AL_columns = uniq(@AL_columns); # only keep unique values in new array
for (my $i = 11; $i < scalar(@HMP_columns); $i++) { # for every column (starting from column 12)
if ($HMP_columns[$i] == "1") {$HMP_columns[$i] = $uniq_AL_columns[0]}
elsif ($HMP_columns[$i] == "2") {$HMP_columns[$i] = $uniq_AL_columns[1]}
elsif ($HMP_columns[$i] == "3") {$HMP_columns[$i] = $uniq_AL_columns[2]}
elsif ($HMP_columns[$i] == "4") {$HMP_columns[$i] = $uniq_AL_columns[3]}
elsif ($HMP_columns[$i] == "5") {$HMP_columns[$i] = $uniq_AL_columns[4]}
elsif ($HMP_columns[$i] == "6") {$HMP_columns[$i] = $uniq_AL_columns[5]}
elsif ($HMP_columns[$i] == "7") {$HMP_columns[$i] = $uniq_AL_columns[6]}
elsif ($HMP_columns[$i] == "8") {$HMP_columns[$i] = $uniq_AL_columns[7]}
elsif ($HMP_columns[$i] == "9") {$HMP_columns[$i] = $uniq_AL_columns[8]}
}
my $joined_HMP = join ("\t", @HMP_columns); # get back to tab separated lines
print "$joined_HMP\n";
}
线的格式化工作,我希望它的工作方式,但是,剧本似乎只对输入图像的每2线工作,或者至少只返回每第二行。我试图以许多不同的方式启动while循环,并尝试了很多其他的东西,比如在while循环之外启动数组,但没有任何效果。任何人都可以告诉我脚本中哪里出错了吗? (顺便说一句,我知道风格并不漂亮,所以如果你们中的任何人对如何使这个脚本更加紧凑有一些建议,请随时这样做!我想学习毕竟。)
你忽略在while
声明中提取行并在split
中提取另一行。
下面请找到固定代码。当AL的线路多于HNP时,它不能检测到情况。
while (<$HMP>) {
my @HMP_columns = split (/\t/, $_);
if(not defined($_ = <$AL>)) {
die "HMP longer than AL";
}
my @AL_columns = split (/\t/, $_);
在每个循环中,您从每个文件读取两次。一旦进入while状态条件,并且一次进入while状态。
替换您同时符合:
use IO::Handle;
while (!($HMP->eof() or $AL->eof()) {
这将导致病情的同时,如果任一文件达到最终失败。 如果文件有可能具有不同的长度,可以在while循环之后检查哪个文件没有达到eof。
几个简单的诀窍:
只要你有非常类似的重复的代码行,这是有可能做的事情更经济的方式的标志。例如,下面的代码:
for (my $i = 11; $i < scalar(@HMP_columns); $i++) { # for every column (starting from column 12)
if ($HMP_columns[$i] == "1") {$HMP_columns[$i] = $uniq_AL_columns[0]}
elsif ($HMP_columns[$i] == "2") {$HMP_columns[$i] = $uniq_AL_columns[1]}
elsif ($HMP_columns[$i] == "3") {$HMP_columns[$i] = $uniq_AL_columns[2]}
elsif ($HMP_columns[$i] == "4") {$HMP_columns[$i] = $uniq_AL_columns[3]}
elsif ($HMP_columns[$i] == "5") {$HMP_columns[$i] = $uniq_AL_columns[4]}
elsif ($HMP_columns[$i] == "6") {$HMP_columns[$i] = $uniq_AL_columns[5]}
elsif ($HMP_columns[$i] == "7") {$HMP_columns[$i] = $uniq_AL_columns[6]}
elsif ($HMP_columns[$i] == "8") {$HMP_columns[$i] = $uniq_AL_columns[7]}
elsif ($HMP_columns[$i] == "9") {$HMP_columns[$i] = $uniq_AL_columns[8]}
}
可重构 - 的$HMP_columns[$i]
新值$uniq_AL_columns[ $HMP_columns[$i-1] ]
,因此整个块可以被改写为
for (my $i = 11; $i < scalar(@HMP_columns); $i++) {
$HMP_columns[$i] = $uniq_AL_columns[$HMP_columns[$i-1]];
}
如果你正在处理阵列中,splice function对于进行各种操作非常方便 - 从数组中删除元素,用其他元素替换它们等等。 shift @AL_columns for 0..4
可写为splice(@AL_columns, 0, 5);
(即,从元素0开始从@AL_columns中移除5个元素)。
对于任何perl工作,在开发脚本时编写调试语句和测试确实有帮助,这样您就可以确定知道发生了什么。在脚本执行时用自己的代码*地声明变量的值,这些语句在调试过程中确实有帮助。一旦代码投入使用,“say”语句可以被注释掉,或者您可以使用环境或程序变量来打开和关闭它们 - 例如,
say "\$a is $a; \%b is " . Dumper(\%b) if $verbose; ## set a variable 'VERBOSE'
如果你还没有发现Data::Dumper,它会成为你最好的朋友在开发过程中:它可以让你检查数据结构和对象的内容,并制定出为什么你精心编写的代码未正常工作这应该!
Perl测试对于覆盖SO答案来说是一个太大的问题,但在perl文档中看看Test和Test::Simple。编写脚本时编写测试套件可以节省大量时间 - 而且比以后更容易!
@i惊慌的外星人:哇非常感谢所有这些有用的提示!我非常感谢他们,因为我几天前才刚刚开始学习perl,所以任何帮助只是欢迎我!我会查找你提到的东西,我相信我会从中获益匪浅! =) – Prawn 2014-09-04 15:33:13
@Prawn很高兴有帮助! :d – 2014-09-04 19:35:40
我对这段代码有一个简短的问题:perl如何知道当你第一次使用$ _(第2行)时,它是第一个文件的行,并且当你第二次使用$ _时(第6行),它是从第二个文件的行?或者说,在这些步骤之间改变$ _的输入的开关在哪里? – Prawn 2014-09-09 08:59:36
在if(...)条件下'$ _'被'$ _ = '重新分配。 – AnFi 2014-09-09 12:32:41