2

我需要帮助弄清楚这两个子例程如何工作以及它们返回什么值或数据结构。这是代码的最小表示:

#!/usr/bin/perl
use strict; use warnings;

# an array of ASCII encrypted characters
my @quality = ("C~#p)eOA`/>*", "DCCec)ds~~", "*^&*"); # for instance

# input the quality
# the '@' character in front deferences the subroutine's returned array ref 
my @q = @{unpack_qual_to_phred(@quality)};

print pack_phred_to_qual(\@q) . "\n";

sub unpack_qual_to_phred{
    my ($qual)=@_;
    my $upack_code='c' . length($qual);
    my @q=unpack("$upack_code",$qual);
    for(my $i=0;$i<@q;$i++){
        $q[$i]-=64;
    }
    return(\@q);
}

sub pack_phred_to_qual{
    my ($q_ref)=@_;
    @q=@{$q_ref};
    for(my $i=0;$i<@q;$i++){
        $q[$i]+=64;
    }
    my $pack_code='c' . int(@q);
    my $qual=pack("$pack_code",@q);

    return ($qual);
}


1;

据我了解,该unpack_qual_to_phread()子例程显然会解密存储在@quality. 该子例程读入一个包含 ASCII 字符元素的数组。数组的每个元素都经过处理并明显解密。然后,子例程返回一个包含解密数组元素的数组 ref。我对此非常了解,但是我对 Perl 函数packunpack. 我也无法在网上找到任何好的例子。

我认为pack_phred_to_qual子程序将质量数组 ref 转换回 ASCII 字符并打印它们。

谢谢。非常感谢任何帮助或建议。此外,如果有人可以提供一个简单的例子来说明 Perlpackunpack函数是如何工作的,那也会有所帮助。

4

3 回答 3

3

这很简单,就像打包一样。Is 正在调用unpack("c12", "C~#p)eOA/>*)`,它依次获取每个字母并找到该字母的 ascii 值,然后从该值中减去 64(嗯,减去 64 是一个后处理步骤,与打包无关)。所以字母“C”是ascii 67,67-64是3。因此该函数的第一个值是3。接下来是“~”,即ascii 126。126-64是62。接下来是#,即ascii 35 , 35-64 是 -29 等等。

从您的脚本生成的完整数字集是:

3,62,-29,48,-23,37,15,1,32,-17,-2,-22

“加密”步骤只是颠倒了这个过程。添加 64,然后转换为 char。

于 2012-07-17T04:25:00.920 回答
3

无需计算长度。这些功能可以简化为

sub unpack_qual_to_phred { [ map $_ - 64, unpack 'c*', $_[0] ] }
sub pack_phred_to_qual { pack 'c*', map $_ + 64, @{ $_[0] } }

在加密方面,这是一个疯狂的简单替换密码。它只是从每个字符的字符数中减去 64。它可以写成

sub encrypt { map $_ - 64, @_ }
sub decrypt { map $_ + 64, @_ }

打包/解包根本不考虑加密/解密;这只是迭代每个字节的一种方式。

于 2012-07-17T04:32:14.470 回答
1

这不是您问题的完整答案,但是您是否阅读过 perlpacktut?或者perldoc上的打包/解包文档?这些可能对帮助您理解有很大帮助。

编辑:

这是一种简单的思考方式:假设您在内存中存储了一个 4 字节的数字 1234。如果它在 perl 标量 $num 中,那么

pack('s*', $num)

会回来

π♦

或“1234”的实际内部存储值是什么。因此pack()将标量值视为字符串,并将其转换为数字的实际二进制表示(您会看到“pi-diamond”打印出来,因为那是该数字的 ASCII 表示)。反过来,

unpack('s*', "π♦")

将返回字符串“1234”。


您的子程序的unpack()一部分unpack_qual_to_phred()可以简化为:

my @q = unpack("c12", "C~#p)e0A`/>*");

这将返回一个 ASCII 字符对列表,每对对应于第二个参数中的一个字节。

于 2012-07-17T04:21:53.267 回答