在 eval() 中使用 Python 正则表达式匹配

Using Python regex matches in eval()

我想利用用户输入来匹配和重新排列字符串。 在 Perl 中,一个简单的示例如下所示:

use strict;

my $str = 'abc123def456ghi';
my $user_input1 = '(\d+).+?(\d+)';
my $user_input2 = '.';
if ($str =~ /$user_input1/) {
  my $newstr = eval($user_input2);
  print $newstr;
}
else {print "No match..."};

原则上同样适用于 Python:

import re

mystr = 'abc123def456ghi'
user_input1 = '(\d+).+?(\d+)'
user_input2 = 'm.group(2) + m.group(1)'
m = re.search(user_input1,mystr)
if m:
    newstr = eval(user_input2)
    print (newstr)
else: print ("No match...")

结果:456123

但是,如果您必须在输入字段中多次键入表达式 'm.group(1)''m.group(2)',则表达式不是很友好。

因此,我想知道在Python中是否有类似于Perl中的'' ''的紧凑表达式? 我无法在 Python 和 '''' 中使用它。 有什么想法吗?

编辑:

对不起,我试着在下面的一些评论后解释: 我正在尝试 eval() 因为它似乎可以与 m.group(1) 等一起使用。 但显然由于某种原因 r'' 等在 eval()

中不被接受
import re
mystr = 'abc123def456ghi'
user_input1 = r'(\d+).+?(\d+)'
user_input2 = r''
newstr = eval(user_input2)
print (newstr)

结果

SyntaxError: unexpected character after line continuation character

关于使用re.sub()

的建议

应该不是简单的字符串替换,而是重排+匹配。 如果我修改原始正则表达式

user_input1 = r'(.+?)(\d+).+?(\d+)(.+)'

我可以用user_input2 = r'' 然而,例如如果我想在匹配之间添加“999”(当然,r'99'r'+"999"+' 都不会这样做)那么我可能会回来使用 eval()m.group(1) 等。虽然我想让用户输入尽可能简短。也许,我可以使用一些建议的替代品。

"inspired" 由上面的评论,我觉得下面的好像是我问题的答案。 (假设您只有 </code> 到 <code>)。至少,这个解决方案对我来说并不直观和明显(正如 Python 喜欢的那样)。欢迎使用更优雅的结构。

import re

mystr = 'abc123def456ghi'
user_input1 = r'(\d+).+?(\d+)'
user_input2 = r'+"999"+'
user_input2 = re.sub(r'\(\d)',r'm.group()',user_input2,flags=re.S)
m = re.search(user_input1,mystr)
if m:
     newstr = eval(user_input2)
     print (newstr)

您不需要 eval。事实上,you want to avoid eval like the plague.

您可以使用 match.expand 获得相同的输出:

mystr = 'abc123def456ghi'
user_input1 = r'(\d+).+?(\d+)'
user_input2 = r''
match = re.search(user_input1, mystr)
result = match.expand(user_input2)
# result: 456123

关于在匹配项之间插入 999 的示例可以使用 \g<group_number> 语法轻松解决:

mystr = 'abc123def456ghi'
user_input1 = r'(.+?)(\d+).+?(\d+)(.+)'
user_input2 = r'\g<3>999'
match = re.search(user_input1, mystr)
result = match.expand(user_input2)
# result: 456999123

如您所见,如果您需要做的只是四处移动捕获的文本并插入新文本,则正则表达式模块可以满足您的需求。仅当您 确实 必须执行代码时才使用 eval