Regex Perl-合并多个正则表达式而不重新编号?
我需要将多个regexp合并为一个,因此代码如下所示:Regex Perl-合并多个正则表达式而不重新编号?,regex,perl,Regex,Perl,我需要将多个regexp合并为一个,因此代码如下所示: my $s = "jump 0xbdf3487"; #my $s = "move 0xbdf3487"; if ($s =~ m/^(move) ([^ ]+)/) { print "matched '$1' '$2'\n"; } if ($s =~ m/^(
my $s = "jump 0xbdf3487";
#my $s = "move 0xbdf3487";
if ($s =~ m/^(move) ([^ ]+)/) { print "matched '$1' '$2'\n"; }
if ($s =~ m/^(jump) ([^ ]+)/) { print "matched '$1' '$2'\n"; }
if ($s =~ m/^(call) ([^ ]+)/) { print "matched '$1' '$2'\n"; }
变成:
my $s = "jump 0xbdf3487";
#my $s = "move 0xbdf3487";
my @patterns = (
'^(move) ([^ ]+)',
'^(jump) ([^ ]+)',
'^(call) ([^ ]+)'
);
my $re = "(?:" . join("|", @patterns) . ")";
$re = qr/$re/;
if ($s =~ m/$re/) { print "matched '$1' '$2'\n"; }
但是,如果$s
是一个跳转,则这不起作用:
matched '' ''
组合regexp中的匹配项将重新编号:在jump regexp中($1,$2)变成($3,$4),在call one中变成($5,$6),等等
如何在不重新编号的情况下组合这些规则?您可以在正则表达式中使用简单的替换,只使用一个正则表达式:
m/^(move|jump|call) ([^ ]+)/
代码:
my $s = "jump 0xbdf3487";
if ($s =~ m/^(move|jump|call) ([^ ]+)/) {
print "matched '$1' '$2'\n";
}
使用分支重置模式
(?|模式)
(不过您需要Perl 5.10或更高版本)。引用文档():
这是“分支重置”模式,它具有一个特殊属性,即捕获组从每个交替分支的同一起点开始编号
您的代码变成:
use strict;
use warnings;
my $s = "jump 0xbdf3487";
#my $s = "move 0xbdf3487";
my @patterns = (
'(move) ([^ ]+)',
'(jump) ([^ ]+)',
'(call) ([^ ]+)'
);
my $re = "^(?|" . join("|", @patterns) . ")";
$re = qr/$re/;
if ($s =~ m/$re/) { print "matched '$1' '$2'\n"; }
注意,我添加了
使用严格的和使用警告
,不要忘记它们 Perl Regex子模式可以与管道连接在一起,使它们成为交替模式。要将交替模式与表达式模式的其余部分分开,请将它们划分为一组。如果您不想捕获组匹配的内容,请将其设置为非捕获组
例如,模式中捕获组的交替:
(移动|跳转|呼叫)([^]+)
以及在模式内的非捕获组中的交替:
(?:移动|跳转|呼叫)([^]+)
如果您的可选模式很复杂,并且不希望所有模式都在一行中,则可以使用/x修改器将它们用空格分隔开
(向下滚动至“某些修改器的详细信息”)
/x
/x告诉正则表达式解析器忽略大多数
既不是反斜杠,也不在括号内的字符类中。你可以
使用此选项可以将正则表达式分解为(稍微)更多的部分
可读部分。此外,“#”字符被视为元字符
引入一条注释,该注释一直运行到模式的结束分隔符,
或者如果图案延伸到下一行,则延伸到当前行的末尾
线路。因此,这非常类似于普通的Perl代码注释。
(只有在以下情况下,才能在注释中包含结束分隔符:
在它前面加一个反斜杠,所以要小心!)
使用/x意味着如果您想要在
模式(位于括号内的字符类之外,不受影响
通过/x),那么您要么必须将其转义(使用反斜杠或
\或使用八进制、十六进制或{}转义对它们进行编码。它是
尝试通过以下方式将注释继续到下一行无效:
用反斜杠或\Q转义\n
下面是我的例子,说明:
#!/usr/bin/perl
use strict;
use warnings;
my $s = "jump 0xbdf3487";
if ($s =~ /^(
move # first complicated pattern
|
jump # second complicated pattern
|
call # third complicated pattern
)\s([^\ ]+) /x) { # Note I hade to escape the space
# with a backslash because of /x
print "matched '$1' '$2'\n";
}
哪些产出:
匹配的“跳转”0xbdf3487'
很酷,我不知道这一个。在这个简单的例子中,这是完全有意义的。实际上,我正在处理的情况有更多的regexp,而且每个regexp都非常复杂,因此将它们全部合并到一行看起来非常糟糕…@lemonsqueze使用交替连接(管道)是有意义的。或者,如果唯一的问题是可读性,您可以使用/x修饰符来允许空白和注释:“/x告诉正则表达式解析器忽略大多数既不反斜杠也不在括号字符类内的空白。您可以使用它将正则表达式拆分为(稍微)可读性更强的部分。此外,”#“字符被视为引入注释的元字符…”