loris has asked for the wisdom of the Perl Monks concerning the following question:

Hello wiser ones,

How would I pass a regexp as a parameter to a subroutine? I would like to do something like:

changeName($topNodeOfXmlTree,'s/WrongNode/RightNode/');

and have the function recurse through the XML tree and change, in my case, the node names:

sub changeNodeNames { my ($self,$node,$regEx) = @_; my $nodeName = $node->nodeName; $nodeName =~ $regEx; ...

The above, however, does not work.

Thanks for your help,

loris

Replies are listed 'Best First'.
Re: Passing regexp as argument
by Zaxo (Archbishop) on Dec 20, 2004 at 10:10 UTC

    You are trying to pass a whole substitution expression, not just a regex. You need eval STRING to do what you want, eval "\$nodeName =~ $regEx"; Note the escaped sigil in $nodeName. That is to prevent the variable from having its value interpolated before evaluation.

    I'd be inclined to pass the regex and substitution as two arguments and interpolate them

    sub changeNodeNames { my ($self,$node,$regEx,$subst) = @_; my $nodeName = $node->nodeName; $nodeName =~ s/$regEx/$subst/; # . . . } $foo->changeNodeNames($anode, qr/foo/, 'bar');

    After Compline,
    Zaxo

Re: Passing regexp as argument
by edan (Curate) on Dec 20, 2004 at 09:56 UTC

    Pass string and the replacement as 2 arguments:

    $obj->changeName($topNodeOfXmlTree, 'WrongNode', 'RightNode'); sub changeNodeNames { my ($self,$node,$from,$to) = @_; my $nodeName = $node->nodeName; $nodeName =~ s/$from/$to/; ... }
    --
    edan

Re: Passing regexp as argument
by BUU (Prior) on Dec 20, 2004 at 16:34 UTC
    The others before me have answered the exact question you asked, namely how you pass a regex, but if you want a slightly more flexible solution (and better than a string eval), you should consider passing a subreference, which you then call to modify node name. For your code above would look like:
    sub change_node_names { my ($self, $node, $code) = @_; $nodeName = $code->( $nodeName ) } $foo->change_node_names( $node, sub { my $name = shift; $name =~ s/wrongnode/rightnode/; return $name } );
    While this requires slightly more effort to call the subroutine, it is much more flexible as you can put literally *any* perl code inside of the annonymous sub, which is what the funnny  sub { } creates.