你可以将文件中的值转换为十六进制吗?

时间:2015-12-15 17:51:00

标签: perl

有没有办法将两个文本文件中的值读取为十六进制并将其总和打印到第三个文件中?

实施例

sym.txt

02 01 04 01

sym2.txt

04 0f 07 09

symout.txt

06 10 0b 0a

这就是我试过的

use strict;
use warnings;

use Data::Dumper;

open my $fh1, '<', 'sym.txt'    or die $!;
open my $fh2, '<', 'sym2.txt'   or die $!;
open my $out, '>', 'symout.txt' or die $!;

while ( !eof( $fh1 ) and !eof( $fh2 ) ) {

    my $line1 = <$fh1>;
    my $line2 = <$fh2>;

    my @l1 = split /\s+/, $line1;
    my @l2 = split /\s+/, $line2;

    my @newvalues;

    my $i = 0;
    for ( @l1 ) {
        push @newvalues, $_ + $l2[$i];
        $i++;
    }

    print Dumper \@newvalues;

    for ( my $i = 0; $i < @newvalues; $i++ ) {
        $newvalues[$i] = sprintf( '%3x', $newvalues[$i] );
    }

    my $new = join( '', @newvalues );

    print $out $new . "\n";
}

它打印十六进制值但不是全部打印,并且它不会从文件中读取十六进制,而是从文件中读取实际值。

2 个答案:

答案 0 :(得分:3)

这类似于你所拥有的,但使用较少的中间内容,并且我使用map进行列表转换而不是for循环。

use strict;
use warnings;

open(my $in1, '<', 'in1.txt') or die $!;
open(my $in2, '<', 'in2.txt') or die $!;
open(my $out, '>', 'out.txt') or die $!;

while (!eof($in1) && !eof($in2)) {
    my @vals1 = split(' ', <$in1>);
    my @vals2 = split(' ', <$in2>);
    my @sums  = map { hex($vals1[$_]) + hex($vals2[$_]) } 0..$#vals1;

    print $out join(' ', map { sprintf('%.2x', $_) } @sums) . "\n";
}

close($in1);
close($in2);
close($out);

答案 1 :(得分:0)

这对你有用

它可能更复杂,因为它遵循您的示例并且满足具有不同数量的值的记录并且将任何缺少的元素默认为零

我还允许每个总共最多三个十六进制数字,因为0xFF + 0xFF是0x1FE

请注意,在空格上拆分字符串的正确方法是使用单个文字空间作为第一个参数。 SubscriptionClient.OnMessage错了

此程序需要将两个输入文件的路径作为命令行上的参数

split /\s+/

输出

use strict;
use warnings 'all';

open my $fh1, '<', $ARGV[0];
open my $fh2, '<', $ARGV[1];

open my $fh_out, '>', 'symout.txt' or die $!;

until ( eof $fh1 or eof $fh2 ) {

    my @l1 = map hex, split ' ', <$fh1>;
    my @l2 = map hex, split ' ', <$fh2>;

    my $n = @l2 > @l1 ? @l2 : @l1;

    my @sum = map {
        no warnings 'uninitialized';
        $l1[$_] + $l2[$_];
    } 0 .. $n-1;

    @sum = map { sprintf '%03X', $_ } @sum;

    print { $fh_out } "@sum\n";
}

更新

要将每个总和截断为8位,您应该将赋值更改为006 010 00B 00A 到此

@sum

您还可以将 my @sum = map { no warnings 'uninitialized'; ( $l1[$_] + $l2[$_] ) & 0xFF; } 0 .. $n-1; 中的格式说明符更改为sprint,因为永远不会有任何大于两位的十六进制值