有没有找到字符串最具体模式的方法?

时间:2014-04-10 09:41:30

标签: ruby regex

我想知道是否有一种方法可以生成与给定字符串匹配的最具体的正则表达式(如果存在这样的事物)。这是我想要方法的例子:

str = "(17 + 31)"
find_pattern(str)
# => /^\(\d+ \+ \d+\)$/ (or something more specific)

我的直觉是通过循环Regex.new并检查str\d等已知模式,使用\s来累积所需的模式。我怀疑这样做很简单。

1 个答案:

答案 0 :(得分:2)

这实质上是算法压缩问题。匹配已知字符串列表的最简单方法是使用Regexp.union工厂方法,但只是依次尝试每个字符串,它不会做任何事情"聪明":

combined_rx = Regexp.union( "(17 + 31)", "(17 + 45)" )
 => /\(17\ \+\ 31\)|\(17\ \+\ 45\)/ 

这对于构建多阶段验证器仍然很有用,而无需编写循环来检查它们。

然而,一个通用的模式匹配器可以找出你的意味着什么以匹配示例,这实际上是不可能的。有太多方法可以将字符串视为相似或不相似。我能想到的最接近的是遗传编程,你提供了一个匹配/不匹配字符串的大型列表,代码通过构造随机Regexp对象(本身就是一个挑战)来猜测最好的正则表达式,看看如何准确地说它们匹配并且不匹配你的例子。最好的匹配器可以组合并变异并再次尝试,直到您获得100%的准确性。这可能是一个有趣的项目,但最终目的是为了大多数目的,而不是自己从问题描述中编写正则表达式。

如果您的问题受到严重限制 - 例如任何示例整数总是可以被\d+替换,\s+等任何示例空格都可以替换,然后您可以通过字符串替换"匹配单位",实际上使用相同的正则表达式依次检查。例如。如果您匹配\A\d+,则使用字符串中的匹配项,并将\d+添加到您的正则表达式中。然后取出字符串的其余部分并查找下一个匹配模式。以这种方式工作将有其局限性(您必须事先知道要匹配的完整模式集,并且所有示例都必须是明确的)。然而,它比遗传程序更容易处理。