给定一个字符串,生成一个可以解析*类似*字符串的正则表达式

时间:2009-04-22 09:00:14

标签: java regex

例如,给定字符串“2009/11/12”我想获得正则表达式(“\ d {2} / d {2} / d {4}”),所以我将能够匹配“2001/01/02”也是。

有什么能做到的吗?相似的东西?任何想法'如何做到这一点?

11 个答案:

答案 0 :(得分:25)

text2re,一个免费的基于网络的“正则表达式”生成器。

我不认为这在源代码中可用。我敢说没有自动正则表达式生成器可以在没有用户干预的情况下正确使用它,因为这需要机器知道你想要的东西。


请注意,text2re使用基于模板,模块化和非常通用的方法来生成正则表达式。它生成的表达式有效,但它们比同等的手工制作表达式复杂得多。它不是学习正则表达式的好工具,因为它在设置示例时做得非常糟糕。

例如,字符串"2009/11/12"将被识别为yyyymmdd模式,这很有帮助。该工具将其转换为 125个角色怪物:

((?:(?:[1]{1}\d{1}\d{1}\d{1})|(?:[2]{1}\d{3}))[-:\/.](?:[0]?[1-9]|[1][012])[-:\/.](?:(?:[0-2]?\d{1})|(?:[3][01]{1})))(?![\d])

手工制作的等效物仅占五分之二(50个字符):

([12]\d{3})[-:/.](0?\d|1[0-2])[-:/.]([0-2]?\d|3[01])\b

答案 1 :(得分:11)

无法为您的问题编写一般解决方案。麻烦的是,任何生成器可能都不知道你要检查什么,例如还应该允许“2312/45/67”吗? “2009.11.12”怎么样?

你能做的就是自己编写一个适合你确切问题的发生器,但是一般的解决方案是不可能的。

答案 2 :(得分:4)

对不起,但你们所谓的不可能显然是一项可以实现的任务。它不能给出所有例子的结果,也许不是最好的结果,但你可以给它各种提示,它会让生活变得简单。下面将举几个例子。

翻译结果的可读输出也非常有用。 类似的东西:

  • “搜索:以非数字字母开头并以字符串结尾的字词:”ing“。
  • 或:搜索:其中包含bbb的文字,其后是zzz
  • 或:*搜索:看起来如此“aa / bbbb / cccc”的模式,其中“/”是分隔符,“aa”是两位数,“bbbb”是任意长度的单词,“cccc”是1900年至2020年之间的四位数*

也许我们可以使用SQL类型的语言创建一个“后台翻译器”来创建正则表达式,而不是以怪诞的方式创建它。

以下是一些可行的例子:

class Hint: 
  Properties: HintType, HintString
  enum HintType { Separator, ParamDescription, NumberOfParameters }
  enum SampleType { FreeText, DateOrTime, Formatted, ... }
  public string RegexBySamples( List<T> samples, 
         List<SampleType> sampleTypes, 
         List<Hint> hints, 
         out string GeneralRegExp, out string description, 
         out string generalDescription)...

regex = RegExpBySamples( {"11/November/1999", "2/January/2003"}, 
                     SampleType.DateOrTime, 
                     new HintList( HintType.NumberOfParameters, 3 ));

regex = RegExpBySamples( "123-aaaaJ-1444", 
                         SampleType.Format, HintType.Seperator, "-" );

用于标记示例文本或输入文本的GUI,也可以添加到正则表达式。 首先标记一个日期(“样本”),然后选择是否已经格式化了该文本,或者如果您正在构建格式,还要选择格式类型:自由文本,格式化文本,日期,GUID或选择...从现有格式(您可以存储在库中)。

让我们为此设计一个规范,并将其作为开源......任何人都想加入?

答案 3 :(得分:3)

我尝试过一种非常天真的方法:

class RegexpGenerator {

    public static Pattern generateRegexp(String prototype) {
        return Pattern.compile(generateRegexpFrom(prototype));
    }

    private static String generateRegexpFrom(String prototype) {
        StringBuilder stringBuilder = new StringBuilder();

        for (int i = 0; i < prototype.length(); i++) {
            char c = prototype.charAt(i);

            if (Character.isDigit(c)) {
                stringBuilder.append("\\d");
            } else if (Character.isLetter(c)) {
                stringBuilder.append("\\w");
            } else { // falltrought: literal
                stringBuilder.append(c);
            }
        }

        return stringBuilder.toString();
    }

    private static void test(String prototype) {
        Pattern pattern = generateRegexp(prototype);
        System.out.println(String.format("%s -> %s", prototype, pattern));

        if (!pattern.matcher(prototype).matches()) {
            throw new AssertionError();
        }
    }

    public static void main(String[] args) {
        String[] prototypes = {
            "2009/11/12",
            "I'm a test",
            "me too!!!",
            "124.323.232.112",
            "ISBN 332212"
        };

        for (String prototype : prototypes) {
            test(prototype);
        }
    }
}

输出:

2009/11/12 - &gt; \ d \ d \ d \ d / \ d \ d / \ d \ d
我是一个测试 - &gt; \ w \ \ w \ w \ w \ w \ w \ w 我也是!!! - &GT; \ w \ w \ w \ w \ w !!!
124.323.232.112 - &gt; \ d \ d \ d \ d \ d \ d \ d \ d \ d \ d \ d \ d
ISBN 332212 - &gt;

正如其他人已经概述的那样,这个问题的一般解决方案是不可能的。此类仅适用于少数情况

答案 4 :(得分:1)

不,你不能得到一个与你想要的可靠匹配的正则表达式,因为正则表达式不包含关于输入的语义信息(即它需要知道它为日期生成正则表达式)。如果问题仅与日期有关,我建议您尝试使用多个正则表达式,看看其中一个是否与所有正则表达式匹配。

答案 5 :(得分:1)

我不确定这是否可行,至少没有很多样本字符串和一些学习算法。

有很多正则表达式会匹配,并且一个简单的算法不可能选择“正确的”算法。你需要给它一些分隔符或其他东西来寻找,所以你也可以自己编写正则表达式。

答案 6 :(得分:1)

听起来像机器学习问题。您必须手头有多个示例(更多),并指示每个示例是否被视为匹配。

答案 7 :(得分:1)

Loreto几乎就是这样。它是一个开源实现,使用常见的最长子串来生成正则表达式。但是,当然需要多个例子。

答案 8 :(得分:0)

我不记得这个名字,但如果我的计算单元理论在理论上对我有用,那么理论上是不可能的。)

答案 9 :(得分:0)

我没有找到任何可以做到这一点,但由于问题域相对小(你会惊讶有多少人使用最奇怪的日期格式),我能够写某种“日期正则表达式生成器”。 一旦我对单元测试感到满意,我就会发布它 - 以防万一有人会需要这样的东西。

感谢所有回答的人(排除了(。*)的人 - 笑话很棒,但这个是sssssssssoooo跛脚:))

答案 10 :(得分:0)

除了提供“好”输入的学习算法示例之外,您还可以将其输入“坏”输入,以便知道不要查找的内容。例如,电话号码中没有字母。