繁体   English   中英

正则表达式实现与事件驱动的匹配?

[英]Regex implementation with event driven matches?

这听起来有些奇怪,但是对我来说将非常有用。 是否有使用基于事件的模型进行匹配的正则表达式实现(任何语言,但最好是java,javascript,c,c ++)?

我希望能够通过基于事件的模型在字符串中注册一堆我正在寻找的不同正则表达式,通过正则表达式引擎输入字符串,并正确触发事件。 像这样的东西存在吗?

我意识到这与重型词法分析器/分析器的边界差不多,但是我希望尽可能避免这样做,因为我的搜索表达式必须是动态的(完全)。

谢谢

这在Perl正则表达式中非常容易做到。 您要做的就是以可以想象到的最直接的方式在模式的适当位置插入事件标注。

首先,想象一下从字符串中提取十进制数字的模式:

my $rx0 = /[+-]?(?:\d+(?:\.\d*)?|\.\d+)/;

让我们对其进行扩展,以便我们可以插入标注:

my $rx1 = qr{
    [+-] ?
    (?: \d+
        (?: \. \d* ) ?
      |
        \. \d+
    )
}x;

对于标注,我将仅打印一些调试信息,但是您可以执行任何所需的操作:

my $rx2 = qr{
    (?: [+-]                (?{ say "\tleading sign"                })
    ) ?
    (?: \d+                 (?{ say "\tinteger part"                })
        (?: \.              (?{ say "\tinternal decimal point"      })
            \d*             (?{ say "\toptional fractional part"    })
        ) ?
      |
        \.                  (?{ say "\tleading decimal point"       })
        \d+                 (?{ say "\trequired fractional part"    })
    )                       (?{ say "\tsuccess"                     })
}x;

这是整个演示:

use 5.010;
use strict;

use utf8;

my $rx0 = qr/[+-]?(?:\d+(?:\.\d*)?|\.\d+)/;

my $rx1 = qr{
    [+-] ?
    (?: \d+
        (?: \. \d* ) ?
      |
        \. \d+
    )
}x;

my $rx2 = qr{
    (?: [+-]                (?{ say "\tleading sign"                })
    ) ?
    (?: \d+                 (?{ say "\tinteger part"                })
        (?: \.              (?{ say "\tinternal decimal point"      })
            \d*             (?{ say "\toptional fractional part"    })
        ) ?
      |
        \.                  (?{ say "\tleading decimal point"       })
        \d+                 (?{ say "\trequired fractional part"    })
    )                       (?{ say "\tsuccess"                     })
}x;

my $string = <<'END_OF_STRING';

    The Earth’s temperature varies between
    -89.2°C and 57.8°C, with a mean of 14°C.

    There are .25 quarts in 1 gallon.

    +10°F is -12.2°C.

END_OF_STRING

while ($string =~ /$rx2/gp) {
    printf "Number: ${^MATCH}\n";
}

运行时会产生以下结果:

        leading sign
        integer part
        internal decimal point
        optional fractional part
        success
Number: -89.2
        integer part
        internal decimal point
        optional fractional part
        success
Number: 57.8
        integer part
        success
Number: 14
        leading decimal point
        leading decimal point
        required fractional part
        success
Number: .25
        integer part
        success
Number: 1
        leading decimal point
        leading sign
        integer part
        success
Number: +10
        leading sign
        integer part
        internal decimal point
        optional fractional part
        success
Number: -12.2
        leading decimal point

您可能希望安排一个更具语法性的正则表达式以实现可维护性。 当您要使用递归下降解析器时,这也很有帮助。 (是的,当然可以做到这一点:毕竟这是Perl。

请查看此答案中的最后一个解决方案,以了解我所说的语法正则表达式。 在SO的其他地方,我也有较大的示例。

但是听起来您应该看一下Damian Conway的Regexp::Grammars模块,它是为这种事情而构建的。 这个问题对此进行了讨论,并有一个指向正确模块的链接。

您可能想看看PIRE-一种非常快速的基于自动机的正则表达式引擎,已进行了调整,可将成千上万的文本行与许多正则表达式快速匹配。 它在C语言中可用,并且具有一些绑定。

如果找不到任何现有的库,那么将其组合在一起并不是一件很难的事。

像这样:

public class RegexNotifier {
   private final Map<Pattern, List<RegexListener>> listeners = new HashMap<Pattern, List<RegexListener>>();

   public synchronized void register(Pattern pattern, RegexListener listener) {
      List<RegexListener> list = listeners.get(pattern);
      if (list == null) {
         list = new ArrayList<RegexListener>();
         listeners.put(pattern, list);
      }
      list.add(listener);
   }

   public void process(String input) {
      for (Entry<Pattern, List<RegexListener>> entry : listeners.entrySet()) {
         if (entry.getKey().matcher(input).matches()) {
            for (RegexListener listener : entry.getValue()) {
               listener.stringMatched(input, entry.getKey());
            }
         }
      }
   }
}

interface RegexListener {
   public void stringMatched(String matched, Pattern pattern);
}

我看到的唯一缺点是Pattern不实现hashCode()equals() ,这意味着如果使用使用不同实例的相等模式,则它将不理想。 但这通常不会发生,因为工厂方法 Pattern.compile()很好地缓存了模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM