开发者

changing several expressions in one line in perl

开发者 https://www.devze.com 2023-01-29 21:37 出处:网络
I want to take a line containing several expressions of the same structure, containing 4 digit hexa numbers, and changing the number in that structure according to a hash table. I tried using this nex

I want to take a line containing several expressions of the same structure, containing 4 digit hexa numbers, and changing the number in that structure according to a hash table. I tried using this next peace of code:

while ($line =~ s/14'h([0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f])/14'h$hash_point->{$1}/g){};

Where $hash_point is a pointer to the hash table.

But it tells me that I try to use an undefined value, when I tried running the fallowing code:

while ($line =~ s/14'h([0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f])/14'h----/g){print $1," -> ",$hash_point->{$1},"\n";};开发者_Go百科

It changed all the wanted numbers to "----" but printed out the values only 2 times (there were much more changes).

Where is the problem?


This is what I used in the end:

$line =~ s/14'h([0-9a-f][0-9a-f][0-9a-f][0-9a-f])/"14'h".$hash_point->{$1}/ge;

and in order to account for numbers not in the hash I've added:

$line =~ s/14'h([0-9a-f][0-9a-f][0-9a-f][0-9a-f])/"14'h".((hash_point->{$1}) or ($1))/ge;

I also wanted to know what numbers don't appear at the hash:

$line =~ s/14'h([0-9a-f][0-9a-f][0-9a-f][0-9a-f])/"14'h".(($hash_point->{$1}) or (print "number $1 didn't change\n") &&($1))/ge;

and finaly, I wanted to be able to control whether the massage from the previous stage would be printed, I've added the use of $flag which in defined only if I want the massages to appear:

$line =~ s/14'h([0-9a-f][0-9a-f][0-9a-f][0-9a-f])/"14'h".(($hash_point->{$1}) or (((defined($flag)) && (print "number $1 didn't change\n")) or ($1)))/ge;


Your regexp seems to work well for me except when hexa number is not present in the hash.

I tried:

#!/usr/bin/perl
use 5.10.1;
use strict;
use warnings;
use Data::Dumper;

my $line = q!14'hab63xx14'hab88xx14'hab64xx14'hab65xx14'hcdef!;
my $hash_point = {
ab63 => 'ONE',
ab64 => 'TWO',
ab65 => 'THREE',
};


while ($line =~ s/14'h([0-9,a-f][0-9,a-f][0-9,a-f][0-9,a-f])/14'h$hash_point->{$1}/g){};

say $line;

This produces:

Use of uninitialized value in concatenation (.) or string at C:\tests\perl\test5.pl line 15.
Use of uninitialized value in concatenation (.) or string at C:\tests\perl\test5.pl line 15.
14'hONExx14'hxx14'hTWOxx14'hTHREExx14'h

The errors are for numbers ab88 and cdef that are not keys in the hash.


Just a small correction, but both of your regexes don't do what you think it does.

/[a-f,0-9]/

Matches any character from a to f, 0 to 9, and a comma. You are looking for

/[a-z0-9]/

Not that this is what is breaking your program (M42 probably got it right, but we can't be sure unless you show us the hash).

Also, apologies, not enough rep to actually answer to other posts.

EDIT: Well, you go through a lot of hoops in that answer, so here's how I'd do it instead:

s/14'h\K(\p{AHex}{4})/if (defined($hash_point->{$1})) {
                          $hash_point->{$1};
                      } else {
                          say $1 if $flag;
                          $1;
                      }/ge

Mainly because chaining and's and &&'s and sosuch generally makes for fairly hard-to-understand code. All whitespace is optional, so squash it for the one-liner!

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号