1

I have the following Perl code, which works without any error. I am wondering if it is possible to make the four replacements in the foreach loop in one pass and delete the whole line matching the fifth replacement. I do not understand the suggested solutions I have gone through so far, I am trying to avoid using hashes. I will be most appreciative.

#!/usr/bin/perl -w
use strict;
use warnings;
                                                                            
my @data=<DATA>;
foreach $lines (@data){
$lines =~ s/\//9/g;
$lines =~ s/333/33300/g;
$lines =~ s/555/55500/g;
$lines =~ s/=|==//g;
$lines =~ s/NIL|N I L//g;       # preferably delete this whole line
}

print "@lines\n";
exit 0;


__DATA__
63740 32575 40606 10217 20159 48528 83230 333 20/// 59008 83820=
63820 32580 20803 10305 20225 40130 82200 333 20262 59009 82823==
63135 NIL=
63742 12570 10507 10208 20148 48509 60014 81100 333 20155 59012 81820=

1 Answer 1

2
my %map = (
   '/'   => '9',
   '333' => '33300',
   '555' => '55500',
   '='   => '',
);

my $pat = join '|', map quotemeta, keys(%map);
my $re = qr/($pat)/;

while (<>) {
   next if /NIL/;
   s/$re/$map{$1}/g;
   print;
}

The above works because the string matched is the key of the translation map. But you want to add the following:

s/^.*NIL.*\z//

There's no simple way to handle that generically. But we could handle that case specially.

my %map = (
   '/'   => '9',
   '333' => '33300',
   '555' => '55500',
   '='   => '',
);

my $pat = join '|', map quotemeta, keys(%map);
my $re = qr/^.*NIL.*\z|($pat)/;

while (<>) {
   s/$re/ defined($1) ? $map{$1} : "" /eg;
   print;
}

This is uglier, though possibly faster. Faster yet would be loading the entire file into memory.

my %map = (
   '/'   => '9',
   '333' => '33300',
   '555' => '55500',
   '='   => '',
   '=='  => '',
);

my $pat = join '|', map quotemeta, keys(%map);
my $re = qr/^.*NIL.*\n?|($pat)/m;

local $/;
while (<>) {
   s/$re/ defined($1) ? $map{$1} : "" /eg;
   print;
}
Sign up to request clarification or add additional context in comments.

8 Comments

Thanks very much @ikegami, this does exactly what I want. I appreciate your time and effort.
Sorry to come back to you @ikegami. The answer is excellent, but when I read data from a file and write the modified data to another file I have a small problem. The print statement prints the modified data ok but starts each line with GLOB(0x56544d5f41e0). When I add "print $OUT_F". OUT_F being the file name the file is empty. The only changes I made are "while (<$IN_F>) {" and "print $OUT_F" inside the while loop.
@Zilore Mumba I think the print statement should be print $OUT_F $_; or print $OUT_F $_, "\n";
print is short for print $_ but print $var is not short for print $var $_. If you want to print $_ to a handle, you'll need to specify it explicitly
@ikegami, sorry to take your time, but for my learning, what are we doing in my $spat = ; and what does $re do? what does s/^.*NIL.*\z// replace?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.