Perl包解包和反向字节顺序

Perl包解包和反向字节顺序,perl,unpack,Perl,Unpack,我试图编写一个脚本,在文本文件中查找十六进制字符串,并将其转换为反向字节顺序。我遇到的问题是有些十六进制字符串是16位的,有些是64位的。我使用Perl的包来打包和解包16位十六进制数,这很好,但64位不行 print unpack("H*", (pack('I!', 0x20202032))). "\n"; #This works, gives 32202020 #This does not print unpack("H*", (pack('I!', 0x4f4232303134303432

我试图编写一个脚本,在文本文件中查找十六进制字符串,并将其转换为反向字节顺序。我遇到的问题是有些十六进制字符串是16位的,有些是64位的。我使用Perl的包来打包和解包16位十六进制数,这很好,但64位不行

print unpack("H*", (pack('I!', 0x20202032))). "\n"; #This works, gives 32202020
#This does not
print unpack("H*", (pack('I!', 0x4f423230313430343239303030636334))). "\n";
我已经用q和q尝试了第二种方法(在这里我得到了ffffffffffff)。我是不是完全错了

作为背景资料,我有一个以千兆字节为单位的管道分隔文本文件,它有十六进制字符串,字节顺序相反,如上所述。此外,文件的列也不标准;有时十六进制字符串出现在一列中,有时出现在另一列中。我需要将十六进制字符串转换为其反向字节顺序。

始终。如果您这样做,您将收到以下消息:

Integer overflow in hexadecimal number at scratch.pl line 8.
Hexadecimal number > 0xffffffff non-portable at scratch.pl line 8.
通过将第二个数字声明更改为
hex('0x4F4232331343034323930306334')
,可以解决这些问题

然而,这个数字仍然太大,
pack'I
无法处理

也许这可以通过简单的字符串操作来实现:

use strict;
use warnings;

my @nums = qw(
    0x20202032
    0x4f423230313430343239303030636334
);

for (@nums) {
    my $rev = join '', reverse m/([[:xdigit:]]{2})/g;
    print "$_ -> 0x$rev\n"
}

__END__
产出:

0x20202032 -> 0x32202020
0x4f423230313430343239303030636334 -> 0x3463633030303932343034313032424f
或处理非偶数长度的数字:

my $rev = $_;
$rev =~ s{0x\K([[:xdigit:]]*)}{
    my $hex = $1;
    $hex = "0$hex" if length($hex) % 2;
    join '', reverse $hex =~ m/(..)/g;
}e;
print "$_ -> $rev\n"
总是。如果您这样做,您将收到以下消息:

Integer overflow in hexadecimal number at scratch.pl line 8.
Hexadecimal number > 0xffffffff non-portable at scratch.pl line 8.
通过将第二个数字声明更改为
hex('0x4F4232331343034323930306334')
,可以解决这些问题

然而,这个数字仍然太大,
pack'I
无法处理

也许这可以通过简单的字符串操作来实现:

use strict;
use warnings;

my @nums = qw(
    0x20202032
    0x4f423230313430343239303030636334
);

for (@nums) {
    my $rev = join '', reverse m/([[:xdigit:]]{2})/g;
    print "$_ -> 0x$rev\n"
}

__END__
产出:

0x20202032 -> 0x32202020
0x4f423230313430343239303030636334 -> 0x3463633030303932343034313032424f
或处理非偶数长度的数字:

my $rev = $_;
$rev =~ s{0x\K([[:xdigit:]]*)}{
    my $hex = $1;
    $hex = "0$hex" if length($hex) % 2;
    join '', reverse $hex =~ m/(..)/g;
}e;
print "$_ -> $rev\n"

为了显得迂腐,您的示例中的十六进制数是32位和128位长,而不是16位和64位。如果最长的一个只有64位长,那么您可以按照您的设想成功地使用
Q
pack
模板(前提是您的perl已编译为支持64位整数)

无论如何都可以使用
pack
/
unpack
解决方案(如果添加了
reverse
,您还必须从十六进制字符串中删除前导
0x
,或从结果中修剪最后两个字符):

举例说明你的价值观:

perl -le 'print unpack "H*", reverse pack "H*", "4f423230313430343239303030636334"'
3463633030303932343034313032424f

为了显得迂腐,您的示例中的十六进制数是32位和128位长,而不是16位和64位。如果最长的一个只有64位长,那么您可以按照您的设想成功地使用
Q
pack
模板(前提是您的perl已编译为支持64位整数)

无论如何都可以使用
pack
/
unpack
解决方案(如果添加了
reverse
,您还必须从十六进制字符串中删除前导
0x
,或从结果中修剪最后两个字符):

举例说明你的价值观:

perl -le 'print unpack "H*", reverse pack "H*", "4f423230313430343239303030636334"'
3463633030303932343034313032424f

真是太棒了!非常感谢。很抱歉,我对perl有点陌生。将其应用为正则表达式替换的最佳方法是作为一个简单的子例程,使用“e”开关在每行中的匹配项上运行?perl-n-i reverse_it.pl myfile.txt。在s{}{}命令的末尾添加一个g标志。reverse_it.pl包含上面的最后一段代码。这非常有效!非常感谢。很抱歉,我对perl有点陌生。将其应用为正则表达式替换的最佳方法是作为一个简单的子例程,使用“e”开关在每行中的匹配项上运行?perl-n-i reverse_it.pl myfile.txt。在s{}{}命令的末尾添加一个g标志。reverse_it.pl包含上面的最后一个代码段。