Reputation: 1500
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=
Upvotes: 1
Views: 77
Reputation: 385789
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;
}
Upvotes: 2