Forum Moderators: coopster & phranque

Message Too Old, No Replies

A few things that I learned recently, s///r and regex $

         

csdude55

7:44 pm on May 2, 2019 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



I've been coding in Perl for somewhere close to 25 years, but I'm totally self taught so I still come across things that I've never seen before (or don't remember seeing, anyway). Maybe it's Day 1 stuff for people with legit education, though, I don't know.

But here are some cool things I've learned this week:

$mod = $text =~ s///r;
The /r modifier keeps it from modifying $text, so only $mod is modified. There's another added benefit, though, that it lets you chain events, like so:

$text = ' csdude   is happy   ';

$mod = $text
=~ s/ +/ /gr
=~ s/^ | $//gr;

print $mod;
# csdude is happy


$&, $`, and $'
In a regular expression, these are predefined variables:

$& => the entire matched string
$` => everything before the matched string
$' => everything after the matched string

$text = 'csdude is happy';
$text =~ /dud/;

print $`;
# cs

print $&;
# dud

print $';
# e is happy

phranque

11:01 pm on May 2, 2019 (gmt 0)

WebmasterWorld Administrator 10+ Year Member Top Contributors Of The Month



TIMTOWTDI...

tangor

11:46 pm on May 2, 2019 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



We are never too old to learn. We are also never to knowledgeable to not gain new info!

csdude55

12:00 am on May 3, 2019 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



One thing I'm not 100% sure on, though, and haven't had a chance to test... if I want to use /r to chain events, do I have to set it equal to a separate string? Or would this be OK?

$text
=~ s/ +/ /gr
=~ s/^ | $//gr;

csdude55

7:07 am on May 3, 2019 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Answering my own question, I think that would only work if I explicitly define the string as $_:

$_ = ' csdude is happy ';

$text
= s/ +/ /gr
= s/^ | $//gr;


[perldoc.perl.org...]

The use of = here instead of =~ is intentional, based on the docs. But since I would be defining a separate variable, anyway, I don't know that there would be any advantage to this above the original.

But the same page seems to imply that if I define $_ as the variable then I can skip the left side of the equation altogether, so (untested):

$_ = ' csdude is happy ';

s/ +/ /g;
s/^ | $//g;

print $_;
# csdude is happy


Now that's interesting... but what if I'm in a subroutine, do I define $_ with:

$_ = $_[0];


?

And I'm guessing that if you're in the middle of a foreach() loop then $_ is already defined separately, so there are limitations on when this format would work?

csdude55

8:24 pm on May 3, 2019 (gmt 0)

WebmasterWorld Senior Member 10+ Year Member Top Contributors Of The Month



Still playing around, but I found that s///r requires a minimum Perl of 5.14. I still have 5.10 and I'm not 100% sure that I want to upgrade.

But using $_ and leaving off the left side of the equation DOES work in 5.10! So as an alternative to using s///r, this worked just fine:

$text = ' csdude  is happy  ';

# using ( ) set $_ equal to $text without modifying $text)
($_ = $text) =~ s/ +/ /g;
s/^ | $//g;

print $_;
# csdude is happy


Also notable that using a foreach() loop with it's own local $_ didn't disrupt anything, but of course I wouldn't be able to refer to $_ within the foreach() and expect it to be the defined $_:

$_ = ' csdude  is happy  ';
s/ +/ /g;
s/^ | $//g;

print $_;
# csdude is happy

@array = ('a', 'b', 'c');

foreach (@array) {
print $_;
# a
# b
# c
}

print $_;
# csdude is happy


And finally, using a subroutine I DID just set $_ equal to $_[0] and it worked as expected:

sub foo {
$_ = $_[0];

s/ +/ /g;
s/^ | $//g;

return $_;
}

print foo(' csdude is happy ');
# csdude is happy