WeBWorK Problems

Regex match capture

Regex match capture

by Steven Fiedler -
Number of replies: 2

I'm observing a difference in behavior between WeBWorK and Perl with regard to the match capture groups.  The below example attempts to search the value 234 for the value 5.  A match is apparently registered in WeBWorK but Perl returns the anticipated result of an unsuccessful match.  I would appreciate any insight on these differing responses.


PG code (Returns a value of 1)

--------------------------------------------------------

DOCUMENT();
loadMacros("PGstandard.pl");

$num="234";

BEGIN_TEXT
WeBWorK match value: \{match($num)\}$BR
END_TEXT

sub match{
    my($foo)  = @_;
    $foo =~ /(5)/;
    if(!defined($1)){return 0; }
    else{ return 1; }
}

ENDDOCUMENT();



Perl code  (Returns a value of 0)

--------------------------------------------------------

  $num="234";
  $ret_val = match($num);
  print "Perl match value: $ret_val\n";

sub match{
    my($foo)  = @_;
    $foo =~ /(5)/;
    if(!defined($1)){ return 0;   }
    else{ return 1; }
}




In reply to Steven Fiedler

Re: Regex match capture

by Alex Jordan -
The difference is not with the match regex, but is with $1.

In PG, where you use $1, that refers to the argument that was passed into the \{...\} block. For example, if you turn your example code into:

```
$num="234";

BEGIN_TEXT
WeBWorK match value: \{match($num)\}$BR
END_TEXT

sub match{
    my($foo)  = @_;
    $foo =~ /(5)/;
    return($1);
}
```

Then the output will be:

WeBWorK match value: match(234)


In reply to Steven Fiedler

Re: Regex match capture

by Glenn Rice -

First, remember that PG is not Perl.  PG is built on Perl, but modifies behavior to achieve convenience for problem authoring as well as security.  So there are always things to watch for.

One thing that you have already seen is the backslash that you need to use a double tilde for instead.

Another thing to watch for is code executed inside a BEGIN_TEXT/END_TEXT block.  Things do not always work as you expect.  If you add "warn match($num)" somewhere outside of the BEGIN_TEXT/END_TEXT block, you will see that the method is returning the correct thing.  What is happening here is that the PG parser inside the BEGIN_TEXT/END_TEXT block is messing with the $1 variable.  If you change your function to

sub match{
    my($foo)  = @_;
    my $test = $foo =~ /(5)/;
    if(!$test){return 0; }
    else{ return 1; }
}

or better

sub match{
    my($foo)  = @_;
    return $foo =~ /(5)/ ? 1 : 0;
}

it will work.

Even better than all of that is to switch to PGML and put this inside of [@ @]* in a BEGIN_PGML/END_PGML block.  Then it works as you have it.