Home > Blockchain >  Is there a way to retain perl regex captures when saving the regular expression as a variable?
Is there a way to retain perl regex captures when saving the regular expression as a variable?

Time:08-16

I'm relatively new to perl and trying to make my code as adaptable as possible for myself to help learn. I'm able to use capture groups when I put the regex directly in my if statement but if I make a $regex variable and use that in the if statement my capture groups no longer work.

My regex variable:

$regex=/([0-9]  bytes) from ([a-z\.-] ) \(([0-9\.] )\).*seq=([0-9] ).*time=([0-9\. ms] )/

My regex check:

 if ($line =~ $regex) {
  print "$4 - $5 - $2 ($3)\n";
 } else {
  print $line;
 }

When I hardcode the regex into the if it works great but the variable returns empty strings. I was hoping I could make this easy to switch between windows/linux ping outputs by providing different regex strings based on the expected output of each command but I'm not finding any easy way to swap out just the regex and maintain the matches.

Expected output (works when hardcoded):

1 - 4.39 ms - myhost.lan (192.168.1.241)
2 - 1.94 ms - myhost.lan (192.168.1.241)
3 - 7.19 ms - myhost.lan (192.168.1.241)
4 - 1.71 ms - myhost.lan (192.168.1.241)

Actual output (when using $regex variable):

 -  -  ()
 -  -  ()
 -  -  ()
 -  -  ()

CodePudding user response:

/.../ (short for m/.../) performs a match. (If =~ isn't used to specify against which variable, $_ is used.) As such, you are effectively assigning false or true to $regex.

You want qr/.../.

my $regex = qr/([0-9]  bytes) from ([a-z\.-] ) \(([0-9\.] )\).*seq=([0-9] ).*time=([0-9\. ms] )/;

CodePudding user response:

Other than using $1, $2, you could assign the result of =~ to an array or a list. Each of capture group would be assigned to ther corresponding positionin the result.

my $text = "5 apples, 6 oranges";
my $pattern = qr/([0-9] ) apples, ([0-9] ) oranges/;

if (my ($appleCount, $orangeCount) = $text =~ m/$pattern/) {
    say $appleCount;
    say $orangeCount;
}

When $text and $pattern don't match, the return value of =~ is an empty list and every values on the LHS would become undef.

Or if you may fancy the named capture groups -- which requires you to rewrite the entire regexp though.

use v5.36;

my $text = "5 apples, 6 oranges";
my $pattern = qr/(?<appleCount>[0-9] ) apples, (?<orangeCount>[0-9] ) oranges/;

if ($text =~ m/$pattern/) {
    say $ {appleCount};
    say $ {orangeCount};
}
  • Related