如何使用 Perl 以单一方式查找多个正则表达式模式



问题已更新

我有(更多(正则表达式模式的列表,例如:(注意:序列非常重要(

([a-z]+)(d+)
}([a-z]+)
([a-z]+)(+|-)
([0-9])](+|-)
...
...

我的输入文件如下:

ce{CO2}  
ce{2CO}  
ce{H2O}  
ce{Sb2O3}  
...
...    

在我的代码中,我找到了每个正则表达式模式,例如

if($string=~m/([a-z]+)(d+)/g) {  my statements ... }
if($string=~m/}([a-z]+)/g) {  my statements ... }
if($string=~m/([a-z]+)(+|-)/g) {  my statements ... }
if($string=~m/([0-9])](+|-)/g) {  my statements ... }

而不是做上面的代码有没有其他方法可以简化代码?

您能否分享您对我改进更好编码的想法。

免责声明:您的问题很难阅读,所以这几乎是猜测。我不确定我是否理解你想做什么。

以动态方式处理数据时,典型的方法是使用调度表。我们可以在这里做类似的事情。通常使用哈希或哈希引用,但由于我们想要特定的顺序,我将改用数组。

my @dispatch = (
{
pattern => qr/f(o)(o)/,
callback => sub {
my ($one, $two) = @_;
print "Found $one and $twon";
},
},
{
pattern => qr/(bar)/,
callback => sub {
my $capture = shift;
print "Saw $capture";
},
},
);

这基本上是搜索模式和相关指令的列表。每个模式都有一个回调,这是一个代码引用。我决定传入捕获变量是有意义的,因为您的模式具有捕获组。

现在为了调用它们,我们迭代调度数组,匹配模式,然后调用关联的回调,传入所有捕获。

my $text = "Foo bar foo bar baz.";
foreach my $search (@dispatch) {
if ($text =~ $search->{pattern}) {
$search->{callback}->(@{^CAPTURE}); # this requires Perl 5.26
}
}

请注意,我使用的是@{^CAPTURE},它在 5.25.7 版中添加到 Perl 中,因此您至少需要稳定的 Perl 5.26 版本才能使用它。(在较旧的 Perl 上,my @capture = $t =~ $search->{pattern}$search->{callback}->(@capture)的行为类似(。

这比拥有if () {}语句列表要优雅得多,因为它很容易扩展。调度表可以基于某些输入动态创建,也可以完全从磁盘读取。

当我们运行此代码时,它会创建以下输出

Found o and o
Saw bar

这不是很壮观,但您应该能够使其适应您的模式。另一方面,我不知道你到底想做什么。如果要修改字符串而不是仅匹配,则可能需要其他参数进行回调。

如果你想了解更多关于调度表的信息,我建议你阅读Mark Jason Dominus的优秀著作High Order Perl的第二章,该书在他的网站上以PDF格式免费提供。

您的问题很难阅读,主要是因为您在正则表达式搜索的末尾有/g(返回一个列表(,但是,您只检查它是否匹配一次。

我做出以下假设

  • 所有匹配项均为必填项
  • 代码可以是单匹配或双匹配
  • 两组在一行中捕获

我想你想要

while ( $string =~ /(([a-z]+)(d+)|}([a-z]+)|([a-z]+)(+|-)|([0-9])](+|-))/g )
{
#$1 has the whole match
#$2 has the first group if defined
#$3 has the second group if defined
}

但是,我更喜欢下面的方法。 这将在一行中捕获

while ($string =~ /([a-z]+d+|}[a-z]+|[a-z]++|-|[0-9]]+|-)/g ) 
{
# in here split the match if required
}

我建议您使用正则表达式注释来使其更清晰。

如果您只想要一个匹配项,请使用

if(
$string=~m/([a-z]+)(d+)/   ||
$string=~m/}([a-z]+)/      ||
$string=~m/([a-z]+)(+|-)/ ||
$string=~m/([0-9])](+|-)/ 
)
{
#some code
}

最新更新