首页 > 解决方案 > 如何使用 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 ... }

除了做上面的代码,还有其他方法可以简化代码吗?

有人可以分享您对我改进以更好地编码的想法。

标签: perl

解决方案


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

当您以动态方式处理数据时,一种典型的方法是使用调度表。我们可以在这里做类似的事情。通常使用散列或散列引用,但由于我们需要特定的顺序,我将使用数组代替。

my @dispatch = (
    {
        pattern => qr/f(o)(o)/,
        callback => sub {
            my ($one, $two) = @_;
            print "Found $one and $two\n";
        },
    },
    {
        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 的优秀著作Higher Order Perl的第二章,该书在他的网站上以 PDF 格式免费提供。


推荐阅读