I need to be able to call a function in a pattern matching statement with the matched patterned as argument and use the return result of the function as replacement for the matched pattern. In perl, one can use eval function to do that. Here is the perl example:
test =~ s/(>?,)(\d )/eval q{&sum($1,$2)}/ge;
How can I do this in Python. Thanks for your help.
CodePudding user response:
Python's parallel to Perl's eval EXPR
is also named eval
.
To be more specific,
eval( $code )
is equivalent to
DOLLAR_AT = None # Global var $@
def perl_eval( code ):
try:
DOLLAR_AT = None
return eval( code )
catch BaseException as err:
DOLLAR_AT = err
perl_eval( code )
But you're actually asking about the parallel of /e
. This is what allows the replacement expression to be a Perl expression. In Python, similar results can be achieved by passing a function for re.sub
's second parameter.
$test =~ s/(\d )\ (\d )/ $1 $2 /eg;
is equivalent to
test = re.sub( r"(\d )\ (\d )", lambda _: str( int( _.group(1) ) int( _.group(2) ) ), test )
Now, let's look at the code you posted. We don't care about $@
here, so the Python equivalent of
$test =~ s/(>?,)(\d )/ eval q{sum( $1, $2 )} /ge;
is
import re
def replacer( match ):
try:
return eval( "sum(" match.group(1) ", " match.group(2) ")" )
except:
return None
test = re.sub( r"(>?,)(\d )", replacer, test )
[Missing: The Perl snippet warns when the replacement expression returns None
.]
That said, this use of eval
is completely wrong.
Because sum(>,123)
is not valid Perl, the Perl snippet is equivalent to
$test =~ s/(>)?,(\d )/ defined( $1 ) ? undef : eval { sum( $2 ) } /ge;
or
import re
def replacer( match ):
if match.group(1) is None:
return None
else
try:
return sum( match.group(2) )
except:
return None
test = re.sub( r"(>)?,(\d )", replacer, test )
[Missing: The Perl snippet warns when the replacement expression returns None
.]
[Python's parallel to eval BLOCK
is try
.]
This makes absolutely no sense. The following is probably closer to the author's intentions:
$test =~ s/(>?,)(\d )/ sum( $1, $2 ) /ge;
or
import re
test = re.sub( r"(>?,)(\d )", lambda _ : sum( _.group(1), _.group(2) ), test )
That might not be it. Passing >,
or ,
to a sub named sum
doesn't seem right. But without knowing what sum
does and what the snippet is supposed to do, I can't comment further.
CodePudding user response:
Here is a link to a post that shows how one can call functions in re;sub in Python! Use of functions in re.sub