For Programmers: Free Programming Magazines  


Home > Archive > PERL Beginners > January 2008 > list or hash of replacement regex









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author list or hash of replacement regex
Bingfeng Zhao

2008-01-22, 4:07 am

Hi list,
I'm in trouble and hope who can work me out.
I want to so some replacements, so I want to keep all replacement
policies in a hash so that I can use them in a foreach loop, such as:

my %policies = (
"abc" => "def",
"jfk\s+" => "jfk ",
"(\d+)uu" => "uu\1"
#... many policies here
);

foreach (<DATA> )
{
s/$_/$policies{$_}/g for keys %policies;
print;
}

But perl complains, so I update it as:
my %policies = (
qr/abc/ => "def",
qr/jfk\s+/ => "jfk ",
qr/\d+uu/ => "uu\1"
);

foreach (<DATA> )
{
s/$_/$policies{$_}/g for keys %policies;
print;
}

The result is wrong, since I got \1 instead of matched part. I update it
again as:
my %policies = (
qr/abc/ => qr/def/,
qr/jfk\s+/ => qr/jfk /,
qr/\d+uu/ => qr/uu\1/
);

foreach (<DATA> )
{
s/$_/$policies{$_}/g for keys %policies;
print;
}

Perl complains again that \1 is not refer to anything. So I try to put
the whole s/// into a list:
my $policies = (
s/abc/def/g,
s/jfk\s+/jfk /g,
s/\d+uu/uu\1/g
);

foreach (<DATA> )
{
$_ =~ $_ for $policies;
print;
}

It generates more errors. So my question, how can I save my replacement
policies in perl data structure so that I can use it just as single one?

Best regards,
Bingfeng




Jeff Pang

2008-01-22, 4:07 am



-----Original Message-----
>From: "Zhao, Bingfeng" <Bingfeng.Zhao@ca.com>
>Sent: Jan 22, 2008 4:53 PM
>To: beginners@perl.org
>Subject: list or hash of replacement regex
>
>But perl complains, so I update it as:
>my %policies = (
> qr/abc/ => "def",
> qr/jfk\s+/ => "jfk ",
> qr/\d+uu/ => "uu\1"
> );


For a first look, you may reversed the hash's keys and values.
Constructing it as below is better.

%policies = (
'def' => qr/abc/,
'jfk' => qr/jfk\s+/,
....);

Regards,
Jeff Pang
John W. Krahn

2008-01-22, 8:09 am

Zhao, Bingfeng wrote:
> Hi list,


Hello,

> I'm in trouble and hope who can work me out.
> I want to so some replacements, so I want to keep all replacement
> policies in a hash so that I can use them in a foreach loop, such as:
>
> my %policies = (
> "abc" => "def",
> "jfk\s+" => "jfk ",
> "(\d+)uu" => "uu\1"


You are using double quoted strings so the backslashes will be
interpolated away and you will be left with:

my %policies = (
"abc" => "def",
"jfks+" => "jfk ",
"(d+)uu" => "uu1"

You need to use single quoted strings instead. Also, the back-reference
\1 is only valid *inside* a regular expression, not in a replacement string:

my %policies = (
'abc' => 'def',
'jfk\s+' => 'jfk ',
'(\d+)uu' => 'uu$1',


> #... many policies here
> );
>
> foreach (<DATA> )
> {
> s/$_/$policies{$_}/g for keys %policies;


You should use a while loop instead of a foreach loop to read from a
file. The current line is in the $_ variable. The substitution
modifies the $_ variable but it now contains one of the keys of
%policies and not the current line. You need to do something like this:

while ( my $line = <FILE> ) {
$line =~ s/$_/$policies{$_}/g for keys %policies;


Now, as to the use of back-references in the replacement string there
are some clues to be found at:

perldoc -q "How can I expand variables in text strings"

Which finally brings us to this:

while ( my $line = <FILE> ) {
$line =~ s/$_/qq{"$policies{$_}"}/eeg for keys %policies;




John
--
Perl isn't a toolbox, but a small machine shop where you
can special-order certain sorts of tools at low cost and
in short order. -- Larry Wall
Rob Dixon

2008-01-22, 8:09 am

Zhao, Bingfeng wrote:
> Hi list,
> I'm in trouble and hope who can work me out.
> I want to so some replacements, so I want to keep all replacement
> policies in a hash so that I can use them in a foreach loop, such as:
>
> my %policies = (
> "abc" => "def",
> "jfk\s+" => "jfk ",
> "(\d+)uu" => "uu\1"
> #... many policies here
> );
>
> foreach (<DATA> )
> {
> s/$_/$policies{$_}/g for keys %policies;
> print;
> }
>
> But perl complains, so I update it as:
> my %policies = (
> qr/abc/ => "def",
> qr/jfk\s+/ => "jfk ",
> qr/\d+uu/ => "uu\1"
> );
>
> foreach (<DATA> )
> {
> s/$_/$policies{$_}/g for keys %policies;
> print;
> }
>
> The result is wrong, since I got \1 instead of matched part. I update it
> again as:
> my %policies = (
> qr/abc/ => qr/def/,
> qr/jfk\s+/ => qr/jfk /,
> qr/\d+uu/ => qr/uu\1/
> );
>
> foreach (<DATA> )
> {
> s/$_/$policies{$_}/g for keys %policies;
> print;
> }
>
> Perl complains again that \1 is not refer to anything. So I try to put
> the whole s/// into a list:
> my $policies = (
> s/abc/def/g,
> s/jfk\s+/jfk /g,
> s/\d+uu/uu\1/g
> );
>
> foreach (<DATA> )
> {
> $_ =~ $_ for $policies;
> print;
> }
>
> It generates more errors. So my question, how can I save my replacement
> policies in perl data structure so that I can use it just as single one?


I suggest:

apply_policies($value);

sub apply_policies {
for ($_[0]) {
s/abc/def/;
s/jfk\s+/jfk /;
s/(\d+)uu/uu\1/;
}
}


HTH,

Rob
Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com