如何在运行时生成正则表达式以匹配数值范围

AAa*_*Aaa 1 java regex

我需要在运行时生成一个与一系列数值匹配的正则表达式.

例如:在运行时我可能会发现,我需要一个正则表达式的所有文件相匹配的"范围" a-261-b.somethinga-543-b.something.

我需要生成一个匹配所有这些文件的正则表达式.有任何想法吗?

我需要用Java编写,所以如果有人知道任何特定于Java的方法,那么它也是可以接受的.

谢谢!

aio*_*obe 13

正则表达式是否适合此任务是值得商榷的.大多数人可能会争辩说不是.

但据我所知,你没有选择,因为你正在使用的API采用正则表达式作为参数,所以这里...

public class NumericRangeRegexGenerator {

    private static String baseRange(String num, boolean up, boolean leading1) {

        char c = num.charAt(0);
        char low  = up ? c : leading1 ? '1' : '0';
        char high = up ? '9' : c;

        if (num.length() == 1)
            return charClass(low, high);

        String re = c + "(" + baseRange(num.substring(1), up, false) + ")";

        if (up) low++; else high--;

        if (low <= high)
            re += "|" + charClass(low, high) + nDigits(num.length() - 1);

        return re;
    }

    private static String charClass(char b, char e) {
        return String.format(b==e ? "%c" : e-b>1 ? "[%c-%c]" : "[%c%c]", b, e);
    }

    private static String nDigits(int n) {
        return nDigits(n, n);
    }

    private static String nDigits(int n, int m) {
        return "[0-9]" + String.format(n==m ? n==1 ? "":"{%d}":"{%d,%d}", n, m);
    }

    private static String eqLengths(String from, String to) {

        char fc = from.charAt(0), tc = to.charAt(0);

        if (from.length() == 1 && to.length() == 1)
            return charClass(fc, tc);

        if (fc == tc)
            return fc + "("+rangeRegex(from.substring(1), to.substring(1))+")";

        String re = fc + "(" + baseRange(from.substring(1), true, false) + ")|"
                  + tc + "(" + baseRange(to.substring(1),  false, false) + ")";

        if (++fc <= --tc)
            re += "|" + charClass(fc, tc) + nDigits(from.length() - 1);

        return re;
    }    

    private static String nonEqLengths(String from, String to) {
        String re = baseRange(from,true,false) + "|" + baseRange(to,false,true);
        if (to.length() - from.length() > 1)
            re += "|[1-9]" + nDigits(from.length(), to.length() - 2);
        return re;
    }

    public static String rangeRegex(int n, int m) {
        return rangeRegex("" + n, "" + m);
    }

    public static String rangeRegex(String n, String m) {
        return n.length() == m.length() ? eqLengths(n, m) : nonEqLengths(n, m);
    }

}
Run Code Online (Sandbox Code Playgroud)

用法

// Generate expression for range 123 - 321
String regexp = NumericRangeRegexGenerator.rangeRegex(123, 321);
Run Code Online (Sandbox Code Playgroud)


说明

下面是对代码的简要说明.

形状范围0000- abcdabcd-9999

首先,我们注意到匹配范围,如0000- abcd非常容易.

例如,表达式000- 527可以表示为

  • [0-4] 后跟两个任意数字,或
  • 5接着00- 27(递归解决!)

形状上的范围1000- abcdabcd- 9999同样容易.

不同长度的下限,上限.

如果"from" - 数字比"to"数字短,则它相当直接.

例如,假设from-number有3位数,to-number有7位数.然后表达式可以如下组成:

  • from- 999(如上所述),
  • 任何4,56位数:[1-9][0-9]{3-5}
  • 1000000- to(如上所述)

相等长度的下限/上限.

这是最棘手的情况(尽管如此仍然不是那么棘手!)

该解决方案再次通过示例进行了最佳描述.考虑范围273- 548.表达式可以由以下部分组成:

  • 2接着73- 99(后面描述的部分),
  • [34] 后跟任意两位数,或
  • 5接着00- 48(后面描述的部分)

  • 什么时候DVD出来了? (3认同)