Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the best way to clear regex matching variables?

What's the best way to clear/reset all regex matching variables?

  • Example how $1 isn't reset between regex operations and uses the most recent match:

    $_="this is the man that made the new year rumble"; 
    / (is) /; 
    / (isnt) /; 
    say $1;          # outputs "is"
    
  • Example how this may be problematic when working with loops:

    foreach (...){
       /($some_value)/;
       &doSomething($1) if $1;
    }
    

Update: I didn't think I'd need to do this, but Example-2 is only an example. This question is about resetting matching variables, not the best way to implement them.

Regardless, originally my coding style was more inline with being explicit and using if-blocks. After coming back to this (Example2) now, it is much more concise in reading many lines of code, I'd find this syntax faster to comprehend.

like image 635
vol7ron Avatar asked Apr 18 '12 20:04

vol7ron


2 Answers

You should use the return from the match, not the state of the group vars.

foreach (...) {
    doSomething($1) if /($some_value)/;
}

$1, etc. are only guaranteed to reflect the most recent match if the match succeeds. You shouldn't be looking at them other than right after a successful match.

like image 95
Mark Reed Avatar answered Oct 07 '22 22:10

Mark Reed


Regex captures* are reset by a successful match. To reset regex captures, one would use a trivial match operation that's guaranteed to match.

"a" =~ /a/;  # Reset captures to undef.

Yeah, it looks weird, but you asked to do some thing weird.

If you fix your code, you don't need weird-looking workarounds. Fixing your code even reveals a bug!

Fixes:

$_ = "this is the man that made the new year rumble"; 
if (/ (is) / || / (isnt) /) {
   say $1; 
} else{ 
   ...  # You're currently printing something random.
}

and

for (...) {
   if (/($some_pattern)/) {
      do_something($1);
   }
}

* — Backrefs are regex patterns that match previously captured text. e.g. \1, \k<foo>. You're actually talking about "regex capture buffers".

like image 22
ikegami Avatar answered Oct 07 '22 20:10

ikegami