为字符串列表创建正则表达式

时间:2013-05-11 16:07:57

标签: regex

我从科学文献中提取了一系列表格,这些表格由列组成,每列都是不同的类型。这是一个示例table of values

我希望能够为每列自动生成正则表达式。显然有一些简单的解决方案,例如.*所以我会添加他们只使用的约束:

  • [A-Z] [a-z] [0-9]
  • 明确的标点符号(例如',''''
  • “简单”量词(例如{3,4}

上表中的“最佳”答案是:

 [A-Z]{3}
 [A-Za-z\s\.]+
 \d{4}\sm
 \d{2}\u00b0\d{2}'\d{2}"N,\d{2}\u00b0\d{2}'\d{2}"E
 (speciosissima|intermediate|troglodytes)
 (hf|sr)
 \d{4}

当然,如果我们移出地理区域,第四个正则表达式会破裂,但软件不知道这一点。目的是收集许多正则表达式,比如说“坐标”并概括它们,可能是部分手动的。仅当存在少量不同的字符串时才会创建枚举。

我很感激能够做到这一点的(特别是F / OSS)软件的例子,特别是在Java中。 (它类似于Google的Refine)。我知道this question 4 years ago,但这并没有真正回答问题和text2re网站似乎是互动的。

注意:我注意到投票结束为“过于本地化”。这是一个非常普遍的问题(给出的表只是一个例子),正如Google / Freebase开发的Refine解决这个问题所示。它可能涉及各种各样的表格(例如财务,新闻等)。这是一个浮点值: enter image description here

自动确定某些权威机构报告实际年龄(例如不是几个月,几天)并使用2位数的精确度会很有用。

3 个答案:

答案 0 :(得分:2)

您的特定问题是“通过演示编程”的特例。也就是说,给定一堆输入/输出示例,您需要生成一个程序。对于您来说,输入是字符串,输出是每个字符串是否属于给定列。最后,您希望使用您提议的有限正则表达式的语言生成程序。

这个通过演示编程的特殊实例似乎与MSR最近的一个项目Flash Fill密切相关。在那里,他们不是为匹配数据生成正则表达式,而是根据输入/输出示例自动生成转换字符串数据的程序。

我只浏览了他们论文的one,但我会尝试列出我在这里理解的内容。

本文基本上有两个重要的见解。第一个是设计 small 编程语言来表示字符串转换。即使使用全开式正则表达式也会创建太多可能快速搜索的可能性。他们设计了自己的抽象语言来操纵字符串;但是,您的约束(例如,仅使用简单的量词)可能会扮演与其自定义语言相同的角色。这在很大程度上是可能的,因为您的特定问题的范围比他们的范围小。

第二个见解是关于如何在这种抽象语言中实际找到与给定输入/输出对匹配的程序。我的理解是,这里的关键思想是使用一种名为version space algebra的技术。关于版本空间代数的粗略想法是,您可以维护可能程序空间的表示,并通过引入其他约束来反复修剪它。这个过程的确切细节远远超出了我的主要兴趣,因此你最好阅读这样的introduction to version space algebra,其中包括一些示例代码。

他们还有一些聪明的方法来排列不同的候选程序,甚至猜测哪些输入可能对已经生成的程序有问题。我看到了一个演示,他们生成了一个程序而没有给它足够的输入/输出对,程序实际上可以突出显示可能不正确的新输入。这种排名非常有趣,但需要一些更复杂的机器学习技术,可能不会立即适用于您的用例。可能仍然很有趣。 (另外,这可能在与我链接的论文不同的论文中详细说明。)

所以是的,长话短说,您可以通过将输入/输出示例提供给基于版本空间代数的系统来生成表达式。我希望有所帮助。

答案 1 :(得分:1)

我自己的方法(我已部分原型化)是启发式的,并且基于这样的前提:给定列通常具有相同或相似字符长度的条目并具有相似的标点符号。我欢迎评论(结果代码将是开源代码)。

  1. [A-Z]展平为'A'
  2. [a-z]展平为'a'
  3. [0-9]展平为'0'
  4. 将任何其他特殊代码点集(例如希腊字符)展平为单个字符(例如alpha)
  5. 然后列成为:

    1. "AAA"
    2. "Aaaaaaaaaa", "Aaaaaaaaaaaaa", "Aaa aaa Aaaaaa"
    3. "0000 a"
    4. "00\u00b000'00"N,00\u00b000'00"E
    5. ...
    6. ...
    7. “0000”
    8. 然后我将用正则表达式替换它们,例如

      1. "([A-Z])([A-Z])([A-Z])"
      2. ...
      3. "(\d)(\d)(\d)(\d)\s([0-9])"
      4. 并将各个角色捕捉到集合中。这将显示(比如说)3中的最终字符始终为"m",因此\d\d\d\d\s[m]和7为[2][0][0][458]

        对于不适合此模型的列,我们使用"(.*)"进行搜索,看看我们是否可以使用启发式创建有用的集合(第5列和第6列),例如“至少2个多字符串而不是超过50%的独特字符串“。

        通过使用动态编程(参见Kruskal),我希望能够对齐类似的正则表达式,这至少对我有用!

答案 2 :(得分:0)

我正在研究相同的(或类似的)(here)。通常,这称为Grammar induction,或者在正则表达式的情况下,它是induction of regular languages。关于这个领域有StaMinA competition。常用算法有RPNI和Blue-Fringe。

Here是另一个相关问题。另外一个here。而here另一个。