Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Perl > Perl Misc > multiple text replacements from a hash

Reply
Thread Tools

multiple text replacements from a hash

 
 
George Mpouras
Guest
Posts: n/a
 
      04-01-2013
Hello,

I have a hash holding "from" - "to" text pieces.
I want to replace on a given text all the "from" parts with the "to".
The following piece of code is working, but I know it is doing not necessary
loops, can you help me to do it better ;



use strict;
use warnings;
use feature qw/say/;

my $text = '172.16.0.36 customer1.com company.comcompany.com erw
172.16.0.36customer1.com';

my %Replace = (
'10.1.1.21' => '192.168.0.9',
'255.255.0.0' => '255.255.255.0',
'customer1.com' => 'local.lan',
'172.16.0.1' => '192.168.0.1',
'company.com' => 'local.lan',
'10.1.31.100' => '192.168.0.7',
'172.16.0.36' => '192.168.0.7',
'10.1.18.105' => '192.168.0.1',
'255.255.240.0' => '255.255.255.0',
'172.16.0.2' => '192.168.0.9');





# We find the min and max hash lengths to avoid later as many iterations is
possible
my $Min_length;
my $Max_length = 0;
foreach my $property (keys %Replace) {
$Max_length = length $Replace{$property} if length $Replace{$property} >
$Max_length;
$Min_length //= $Max_length;
$Min_length = length $Replace{$property} if length $Replace{$property} <
$Min_length;
}



my $offset = 0;
while ( $offset < length $text) {
my $offset_walk = 0;
#say "*$offset* $text";

for (my $i = $Max_length; $i >= $Min_length; $i--) {
my $piece = substr($text, $offset, $i);

if ( exists $Replace{$piece} ) {
substr($text, $offset, $i, $Replace{$piece});
$offset_walk = length $Replace{$piece};
last
}
}

$offset += $offset_walk == 0 ? 1 : $offset_walk;
}


say $text;

 
Reply With Quote
 
 
 
 
Rainer Weikusat
Guest
Posts: n/a
 
      04-01-2013
"George Mpouras"
<(E-Mail Removed) m.com.nospam>
writes:

> I have a hash holding "from" - "to" text pieces.
> I want to replace on a given text all the "from" parts with the
> "to".
>
> my $text = '172.16.0.36 customer1.com company.comcompany.com
> erw 172.16.0.36customer1.com';
>
> my %Replace = (
> '10.1.1.21' => '192.168.0.9',
> '255.255.0.0' => '255.255.255.0',
> 'customer1.com' => 'local.lan',
> '172.16.0.1' => '192.168.0.1',
> 'company.com' => 'local.lan',
> '10.1.31.100' => '192.168.0.7',
> '172.16.0.36' => '192.168.0.7',
> '10.1.18.105' => '192.168.0.1',
> '255.255.240.0' => '255.255.255.0',
> '172.16.0.2' => '192.168.0.9');


Considering that none of your keys is a prefix of another key, the
obvious idea would be to collect them all into a regex:

my $re = join('|', map { quotemeta($_) } keys(%Replace));
$re = qr/($re)/;

and do all replacements with the single s/// statement

$text =~ s/$re/$Replace{$+}/g;

If you had keys which are prefixes of other key, you could use

my $re = join('|', map { quotemeta($_) } sort { $b cmp $a } keys(%Replace));

to prefer the longer match or

my $re = join('|', map { quotemeta($_) } sort keys(%Replace));

to prefer the shorter.

Another good idea might be to use an existing macro (pre-)processor,
eg, m4, for tasks like this.
 
Reply With Quote
 
 
 
 
George Mpouras
Guest
Posts: n/a
 
      04-01-2013

clever, I have taken a wrong path.
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
hash of hash of hash of hash in c++ rp C++ 1 11-10-2011 04:45 PM
Hash#select returns an array but Hash#reject returns a hash... Srijayanth Sridhar Ruby 19 07-02-2008 12:49 PM
Isolate lines in a text file and perform replacements Robert Neville Perl Misc 4 04-03-2007 06:10 PM
Sony InfoLithium Battery Replacements Mike Schudel Digital Photography 2 07-22-2004 12:52 AM
Replacements for BP-511 for Canon cameras Rick Langston Digital Photography 12 03-07-2004 04:03 PM



Advertisments