2012-11-08 206 views
0

我有一串ASCII字符。我使用解压函数将其转换为十六进制字符串。Perl中的十六进制计算

#! /usr/bin/perl 

use strict; 
use warnings; 

my $str="hello"; 
my $value=unpack("H*",$str); 

print $value,"\n"; 

**output:** 68656c6c6f 

现在,让我们说,我想用这个输出的十六进制字节的字符串,每次读一个字节,并在其上进行一些计算和存储在另一个变量输出。

例如,

#! /usr/bin/perl 

use strict; 
use warnings; 

my $str="hello"; 
my $value=unpack("H*",$str); 

my $num=0x12; 
my $i=0; 

while($i<length($value)) 
{ 
    my $result.=(substr($value,$i,2)^$num); 
    $i+=2; 
} 

print $result,"\n"; 

**output:** 

Argument "6c" isn't numeric in bitwise xor (^) at test.pl line 13. 
Argument "6c" isn't numeric in bitwise xor (^) at test.pl line 13. 
Argument "6f" isn't numeric in bitwise xor (^) at test.pl line 13. 
8683202020 

输出不正确,也有几个警告。

如果我们把字符串的第一个十六进制字节,“你好”作为一个例子:

68 xor 12 = 7A 

但是,输出其显示为86.输出是不正确的,也是我不知道如何 它得到了86的输出。

什么是正确的做法呢?

+1

您使用的警告,但您试图访问其范围以外$结果? – ugexe

回答

6

如果以十六进制表示内容,它必然是一个字符串,因为十六进制是一个人类可读的表示的一个数字。你不想要一个字符串;你需要一系列数字,其中每个数字都是char的数值。你可以使用ord度日字符数字符,但unpack还提供了手段:

my @bytes = unpack 'C*', $str; 

你想的处理:

$_ ^= $num for @bytes; 

并重组的字符串:

$str = pack 'C*', @bytes; 

以上三项加起来:

$str = pack 'C*', map $_^$num, unpack 'C*', $str; 

你也可以做到这一点,如下所示:

my $mask = chr($num) x length($str); 
$str ^= $mask; 
+0

谢谢,这很好,但我认为只适用于ASCII字符。我正在处理一个二进制文件,这就是原因,我需要使用字节的十六进制表示。如果我理解它是正确的,你的方法将获得每个字符的ASCII值并对其执行操作。我想用十六进制。 –

+1

@NeonFlash,不,它也适用于二进制字符串。 – cjm

+0

@Neon Flash,你错了。 '^','ord'和'chr'完全不了解ASCII。他们都处理任意字符,这是一个数字的花哨词。 – ikegami