Help with perl special variable

R

Ricky

Hi gurus,
I m reading a regexp and a string from an external file (actually my
program configuration file).
After, I need to do a string matching, using previously loaded regex,
and print the "destination" result, using special variable $2,
hardcoded in my conf.

I have no luck..please give me some hints:

Here is my configuration line:

rule (^.*blabla-dir/blabla-file/)(.*$) /somedirectory/
somefile/$2 LABEL

perl code extract:
....
/(^rule)\s+(.[^\s]+)\s+([\/\w\$]+)\s+(\w+)/
$regex[$i]=$2;
$destination[$i]=$3;
...
...
$_="/blabla-dir/blabla-file/OIAC-ciao";
if ( /$regex[$i]/ ) {
print "$destination[$i]\n";
}
...

The print only show:
/somedir/somepath/$2
but I need to "explode" that $2. Note that if i modify the print as
follows:

print "$2 $destination[$i]\n";

it returns:
OIAC-ciao /somedir/somepath/$2

I'm sure there is a way to do this..but I am a noob programmer

Thanks,
perlnoob
 
R

riccardo.marini

Il giorno mercoledì 11 aprile 2012 14:30:23 UTC+2, Ricky ha scritto:
Hi gurus,
I m reading a regexp and a string from an external file (actually my
program configuration file).
After, I need to do a string matching, using previously loaded regex,
and print the "destination" result, using special variable $2,
hardcoded in my conf.

I have no luck..please give me some hints:

Here is my configuration line:

rule (^.*blabla-dir/blabla-file/)(.*$) /somedirectory/
somefile/$2 LABEL

perl code extract:
...
/(^rule)\s+(.[^\s]+)\s+([\/\w\$]+)\s+(\w+)/
$regex[$i]=$2;
$destination[$i]=$3;
..
..
$_="/blabla-dir/blabla-file/OIAC-ciao";
if ( /$regex[$i]/ ) {
print "$destination[$i]\n";
}
..

The print only show:
/somedir/somepath/$2
but I need to "explode" that $2. Note that if i modify the print as
follows:

print "$2 $destination[$i]\n";

it returns:
OIAC-ciao /somedir/somepath/$2

I'm sure there is a way to do this..but I am a noob programmer

Thanks,
perlnoob

I tried the example in the FAQ with string substitution operator and modifier "eeg".No luck.
I also tried to use "eval", and tried another approach to the problem. Still no luck.
 
R

riccardo.marini

Il giorno mercoledì 11 aprile 2012 16:14:06 UTC+2, (e-mail address removed) ha scritto:
Il giorno mercoledì 11 aprile 2012 14:30:23 UTC+2, Ricky ha scritto:
Hi gurus,
I m reading a regexp and a string from an external file (actually my
program configuration file).
After, I need to do a string matching, using previously loaded regex,
and print the "destination" result, using special variable $2,
hardcoded in my conf.

I have no luck..please give me some hints:

Here is my configuration line:

rule (^.*blabla-dir/blabla-file/)(.*$) /somedirectory/
somefile/$2 LABEL

perl code extract:
...
/(^rule)\s+(.[^\s]+)\s+([\/\w\$]+)\s+(\w+)/
$regex[$i]=$2;
$destination[$i]=$3;
..
..
$_="/blabla-dir/blabla-file/OIAC-ciao";
if ( /$regex[$i]/ ) {
print "$destination[$i]\n";
}
..

The print only show:
/somedir/somepath/$2
but I need to "explode" that $2. Note that if i modify the print as
follows:

print "$2 $destination[$i]\n";

it returns:
OIAC-ciao /somedir/somepath/$2

I'm sure there is a way to do this..but I am a noob programmer

Thanks,
perlnoob

I tried the example in the FAQ with string substitution operator and modifier "eeg".No luck.
I also tried to use "eval", and tried another approach to the problem. Still no luck.

I saw the light..
...
my $test=eval "\"$destination[$i]\"";
print "$test\n";
...

finally shows:
/somedir/somepath/OIAC-ciao

I really can't understand why it needs that kind of quoting ..
Without it, doesn't works..
Can someone explain??
tks
 
R

riccardo.marini

Il giorno mercoledì 11 aprile 2012 18:37:43 UTC+2, Ben Morrow ha scritto:
Quoth (e-mail address removed):
I saw the light..
..
my $test=eval "\"$destination[$i]\"";
print "$test\n";
..

finally shows:
/somedir/somepath/OIAC-ciao

I really can't understand why it needs that kind of quoting ..
Without it, doesn't works..
Can someone explain??

I can try... :).

The first thing that happens is this

"\"$destination[$i]\""

string is evaluated. Since it's double-quoted, it interprets backslashes
specially and interpolates variables, so the result is the string

'"/somedir/somepath/$2"'

I've single-quoted that string to show that it won't be expanded again
(at least, not until you ask for it).

The next thing that happens is that string is passed to eval. This looks
at the string and interprets it as a Perl expression, in this case the
expression

"/somedir/somepath/$2"

. Notice I've removed the single quotes, since this is no longer a
string *containing* a Perl expression, it's an actual Perl expression.
(This distinction is a little confusing, but is at the heart of what
eval does.)

This expression is another double-quoted string, so again variables are
expanded and the result is

'/somedir/somepath/OIAC-ciao'

(I've single-quoted it for the same reason as before), which string is
then assigned to $test.

Thanks m8. Your explainetion is great.
eval is much too powerful a tool for the job you are doing. Even if you
aren't worried about the security implications, the multiple layers of
quoting required get very confusing. Assuming you only want to support
numbered variables in your substitutions, I would use something like
this:

if ( my @capture = /$regex[$i]/ ) {
my $result = $destination[$i];
$result =~ s/\$([0-9]+)/$capture[$1]/eg;
print "$result\n";
}

This expands the variables in the result explicitly, rather than trying
to get perl to do it for you with eval.

Ben

I m now using following code:
...
if ( my @capture = /$regex[$i]/ ) {
my $result = $destination[$i];
print "CAPTURE: @capture\n";
print "BEFORE s//: $result\n";
$result =~ s/\$([0-9]+)/$capture[$1-1]/eg;
print "AFTER s//: $result\n";
}
...

And works fine.
I only added "$1-1' cause "$1" will be out of index in @capture.
This should be safer, and should work against any or multiple $[0-9] in my configuration line.

Can you confirm?

Thanks again Ben
perlnoob.
 
T

Tim McDaniel

I m now using following code:
..
if ( my @capture = /$regex[$i]/ ) {
my $result = $destination[$i];
print "CAPTURE: @capture\n";
print "BEFORE s//: $result\n";
$result =~ s/\$([0-9]+)/$capture[$1-1]/eg;
print "AFTER s//: $result\n";
}
..

And works fine.
I only added "$1-1' cause "$1" will be out of index in @capture.
This should be safer, and should work against any or multiple $[0-9]
in my configuration line.

I think it would be a little better if you sure that a reference is
valid before referring to it.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#! /usr/bin/perl
use strict;
use warnings;

my $regexp = '^(.)(.)'; # boobies!
$_ = 'ABC';
if (my @capture = /$regexp/) {
my $result = 'left $1 right $2 invalid $3';
print "CAPTURE: '", join("' '", @capture), "'\n";
print "BEFORE s//: '$result'\n";
my $bad = 0;
foreach my $ref ($result =~ /\$([0-9]+)/g) {
if (! exists $capture[$ref-1]) {
warn "result '$result' refers to \$$ref, which is not captured in the regexp.\n";
$bad = 1;
}
}
if ($bad) {
die "Dying due to bad element reference.\n";
}
$result =~ s/\$([0-9]+)/$capture[$1-1]/eg;
print "AFTER s//: '$result'\n";
}
exit 0;
 
R

riccardo.marini

Il giorno giovedì 12 aprile 2012 18:01:13 UTC+2, Tim McDaniel ha scritto:
I m now using following code:
..
if ( my @capture = /$regex[$i]/ ) {
my $result = $destination[$i];
print "CAPTURE: @capture\n";
print "BEFORE s//: $result\n";
$result =~ s/\$([0-9]+)/$capture[$1-1]/eg;
print "AFTER s//: $result\n";
}
..

And works fine.
I only added "$1-1' cause "$1" will be out of index in @capture.
This should be safer, and should work against any or multiple $[0-9]
in my configuration line.

I think it would be a little better if you sure that a reference is
valid before referring to it.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

#! /usr/bin/perl
use strict;
use warnings;

my $regexp = '^(.)(.)'; # boobies!
$_ = 'ABC';
if (my @capture = /$regexp/) {
my $result = 'left $1 right $2 invalid $3';
print "CAPTURE: '", join("' '", @capture), "'\n";
print "BEFORE s//: '$result'\n";
my $bad = 0;
foreach my $ref ($result =~ /\$([0-9]+)/g) {
if (! exists $capture[$ref-1]) {
warn "result '$result' refers to \$$ref, which is not captured in the regexp.\n";
$bad = 1;
}
}
if ($bad) {
die "Dying due to bad element reference.\n";
}
$result =~ s/\$([0-9]+)/$capture[$1-1]/eg;
print "AFTER s//: '$result'\n";
}
exit 0;

Nice. I ll protect it using "exists".
I love your regex :)

tks
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top