计算机是否可以通过用户提供的示例“学习”正则表达式?


94

计算机是否可以通过用户提供的示例“学习”正则表达式?

澄清:

  • 不是想学正则表达式。
  • 我想创建一个程序,该程序从用户交互提供的示例中“学习”正则表达式,也许可以通过从文本中选择部分或选择开始或结束标记来实现。

可能吗?我可以使用Google提供的算法,关键字等吗?

编辑:谢谢您的答案,但我对提供此功能的工具不感兴趣。我正在寻找理论信息,例如论文,教程,源代码,算法名称,因此我可以为自己创建一些东西。


4
我很惊讶没有人提到Regex :: PreSuf
Tripleee

Answers:


44

计算学习理论入门》一书包含了一种学习有限自动机的算法。由于每种常规语言都等效于有限的自动机,因此可以通过程序学习一些正则表达式。Kearns和Valiant展示了一些不可能学习有限自动机的情况。一个相关的问题是学习隐马尔可夫模型,这是可以描述字符序列的概率自动机。注意,编程语言中使用的大多数现代“正则表达式”实际上比正则语言要强,因此有时更难学习。


43

是的,有可能,我们可以从示例中生成正则表达式(文本->所需的提取)。这是一个工作正常的在线工具:http : //regex.inginf.units.it/

Regex Generator ++在线工具使用GP搜索算法从提供的示例中生成正则表达式。GP算法由多目标适应性驱动,从而导致更高的性能和更简单的解决方案结构(Occam的Razor)。该工具是的里雅斯特大学机器学习实验室(的里雅斯特大学)的演示应用程序。请在此处查看视频教程。

这是一个研究项目,因此您可以在此处阅读有关使用的算法的信息

看哪!:-)

仅当所提供的示例很好地说明了问题时,才可以从示例中找到有意义的正则表达式/解决方案。考虑以下描述提取任务的示例,我们正在寻找特定的商品代码;示例为文本/提取对:

"The product code is 467-345A" -> "467-345A"
"The item 789-345B is broken"  -> "789-345B"

一个(人类)家伙看着示例,可能会说:“项目代码是\ d ++-345 [AB]之类的东西”

当项目代码更宽松,但我们没有提供其他示例时,我们没有证明可以很好地理解问题。将人工生成的解决方案\ d ++-345 [AB]应用于以下文本时,它将失败:

"On the back of the item there is a code: 966-347Z"

为了更好地描述什么是匹配项,什么不是所需的匹配项,您必须提供其他示例:--ie:

"My phone is +39-128-3905 , and the phone product id is 966-347Z" -> "966-347Z"

电话号码不是产品ID,这可能是重要的证明。


4
这应该是最佳答案。有可能,这证明了这一点。来源可在这里找到:github.com/MaLeLabTs/RegexGenerator
rjurney 2015年

您的产品代码示例说明了为什么上述人员应查找产品代码规范并根据该规范编写正则表达式,而不是尝试从有限的示例产品代码集中推断正则表达式(无论是个人还是程序正在尝试推断正则表达式)。
Jan Goyvaerts'2

2
这是做事的正确方法。我的示例只是从概念上解释问题的一种方法。有时没有规范,或者这个家伙根本无法自己编写正则表达式(缺乏知识)。
法比亚诺·塔劳

2
“的文本提取的例子正则表达式推理”的文章中包含的算法的详细说明machinelearning.inginf.units.it/publications/...
mimmuz

3
这是一个了不起的项目,并且很好地演示了基因编程的强大功能!
rcgeorge23

36

没有任何计算机程序能够基于有效匹配列表来生成有意义的正则表达式。让我告诉你为什么。

假设您提供示例111111和999999,则计算机应生成:

  1. 正则表达式正好匹配这两个示例: (111111|999999)
  2. 匹配6个相同数字的正则表达式 (\d)\1{5}
  3. 正则表达式匹配6个和9个 [19]{6}
  4. 匹配任意6位数字​​的正则表达式 \d{6}
  5. 以上三个中的任何一个,带有单词边界,例如 \b\d{6}\b
  6. 前三个中的任何一个,不能在数字之前或之后,例如 (?<!\d)\d{6}(?!\d)

如您所见,可以通过多种方式将示例概括为正则表达式。计算机构建可预测的正则表达式的唯一方法是要求您列出所有可能的匹配项。然后,它可以生成与这些匹配完全匹配的搜索模式。

如果您不想列出所有可能的匹配项,则需要更高级别的描述。这正是正则表达式旨在提供的。无需提供一长串的6位数字,您只需告诉程序匹配“任意六位数字”即可。在正则表达式语法中,它变为\ d {6}。

提供与正则表达式一样灵活的高级描述的任何方法,也将与正则表达式一样复杂。RegexBuddy之类的所有工具可以使创建和测试高级描述变得更加容易。RegexBuddy允许您使用简单的英语构建块,而不是直接使用简洁的正则表达式语法。但是,它无法为您创建高级描述,因为它无法神奇地知道何时应该归纳您的示例,何时不应该将其归纳。

当然可以创建一个使用示例文本以及用户提供的准则来生成正则表达式的工具。设计此类工具的难点在于,它如何向用户请求所需的指导信息,而不会使该工具比正则表达式本身更难于学习,并且不将该工具限制于普通的正则表达式作业或简单的正则表达式。


没错,发布问题后发现的许多学习算法都需要正面和负面信息。据我了解,因为用户是通过回答问题来提供的,所以不需要明确的“高级描述”。
Daniel Rikowski 09年

如果工具提出问题,则问题和给定答案的组合将形成更高级别的描述。这些工具的质量在很大程度上取决于它提出的问题。
Jan Goyvaerts

这很愚蠢,因为如果您提供了另一个示例,则可以消除其中的一些可能性。另一个例子可以消除更多的问题。
克里斯,2014年

2
@Cris:无论您提供多少样本,原则仍然存在。它只是改变了可能性。例如,添加123456会将#2更改为(\ d)\ 1 {5} | 123456,将#3更改为[19] {6} | 123456。或者可以将#3更改为[1-69] {6}。甚至可能是所需的模式将匹配6个相同的数字或6个数字,其中每个数字都比前一个数字大一个。即使您提供10,000个6位数字的样本,程序也无法在没有用户额外说明的情况下区分#1,#4,#5或#6。
Jan Goyvaerts 2014年

我觉得这个问题很容易解决,如下所示:该程序尝试尽可能通用(在合理的范围内),然后为您提供它认为可以匹配的其他示例。通过简单地对拟议的匹配说出“是”和“否”,就可以帮助它理解您实际试图捕获的内容的范围。我希望看到一个文本编辑器中的工具,该工具使用了此概念并从当前打开的文件中提出了匹配项。
乔恩·麦格隆

9

是的,这肯定是“可能的”。这是伪代码:

string MakeRegexFromExamples(<listOfPosExamples>, <listOfNegExamples>)
{
   if HasIntersection(<listOfPosExamples>, <listOfNegExamples>)
     return <IntersectionError>

   string regex = "";
   foreach(string example in <listOfPosExamples>)
   {
      if(regex != "")
      {
         regex += "|";
      }
      regex += DoRegexEscaping(example);
   }
   regex = "^(" + regex + ")$";

   // Ignore <listOfNegExamples>; they're excluded by definition

   return regex;
}

问题是有无数的正则表达式将匹配示例列表。这段代码提供了集合中最简单/最愚蠢的正则表达式,基本上匹配了肯定示例列表中的所有内容(没有其他,包括任何否定示例)。

我想真正的挑战是找到与所有示例匹配的最短的正则表达式,但是即使那样,用户也必须提供非常好的输入以确保结果表达式是“正确的”。


3
当用户输入正样本和负样本时,它开始变得有趣起来。正则表达式必须匹配正样本,而不匹配负样本。
user55400 2009年

1
@Thomas:我的匹配所有示例,仅此而已!
Daniel LeCheminant 2009年

@blixtor-其实很简单。只是不要在构造的正则表达式中放置任何否定示例,否则它们将被拒绝。请记住,代码构建的代码仅与正面示例匹配;负面例子(以及其他任何东西)被定义排除在外!
Daniel LeCheminant 09年

丹尼尔是对的。如果没有更高层次的描述,则可以从示例列表中一致而准确地推断出所有替代列表。
Jan Goyvaerts's

6

我相信这个词是“归纳法”。您想归纳规则的语法。

我认为有限的示例集(正面或负面)是不可能的。但是,如果我没记错的话,可以咨询Oracle。(基本上,您必须让该程序向用户询问是/否问题,直到它满足为止。)


是的,这就是我想要做的,以交互方式询问用户。
Daniel Rikowski 09年

Yuval F的参考文献似乎是我的初衷,我建议您看一看。
杰伊·科米尼克


4

基于序言,有一种语言专门用于解决此类问题。叫做progol

正如其他人所提到的,基本思想是归纳学习,在AI圈子中通常称为ILP(归纳逻辑编程)。

第二个链接是有关ILP的Wiki文章,如果您有兴趣了解有关该主题的更多信息,则其中包含许多有用的源材料。


2

@Yuval是正确的。您正在研究计算学习理论或“归纳推理”。

这个问题比您想象的要复杂,因为“学习”的定义很简单。一个常见的定义是,学习者可以在需要时吐出答案,但最终必须要么吐出答案,要么总是吐出相同的答案。这假定输入的数量是无限的,并且绝对不会保证程序何时才能做出决定。此外,您无法确定何时做出决定,因为稍后它可能仍会输出一些不同的内容。

通过这个定义,我非常确定常规语言是可以学习的。根据其他定义,没有那么多...



0

如果一个人学习正则表达式是可能的,那么从根本上来说程序是可能的。但是,该程序将需要正确编程才能学习。幸运的是,这是一个相当有限的逻辑空间,因此它不会像教导程序能够看到对象或类似对象那样复杂。


1
并非如此,您应该查找在Turing机器上无法确定的问题。
Stephen Curial

公平地说,我说过如果一个人可以学习REGEX,那么一台机器也可以。我不是一般意思。
cjk

@scurial我认为不存在人们可以解决但在巡回演出机器上无法确定的问题,是吗?
2011年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.