Как создать регулярное выражение во время выполнения, чтобы соответствовать числовому диапазону - PullRequest
1 голос
/ 14 июня 2011

Мне нужно создать во время выполнения регулярное выражение, которое будет соответствовать диапазону числовых значений.

Например: Во время выполнения я могу обнаружить, что мне нужно регулярное выражение, соответствующее всем файлам в«диапазон» a-261-b.something до a-543-b.something.

Мне нужно создать регулярное выражение, которое будет соответствовать всем этим файлам.Любые идеи?

Мне это нужно на Java, так что если кто-нибудь знает какой-либо специфический для Java способ для этого, это также приемлемо.

Спасибо!

Ответы [ 3 ]

13 голосов
/ 14 июня 2011

Вопрос о том, подходят ли регулярные выражения для этой задачи, спорен. Большинство людей, вероятно, утверждают, что это не так.

Однако, насколько я понимаю, у вас нет выбора, поскольку используемый вами 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);
    }

}

Использование

// Generate expression for range 123 - 321
String regexp = NumericRangeRegexGenerator.rangeRegex(123, 321);

1011 *
*

Объяснение

Ниже приведено краткое объяснение кода.

Диапазоны в форме 0000 - abcd и abcd - 9999

Сначала отметим, что сопоставить диапазоны, такие как 0000 - abcd, довольно просто.

Выражение, например 000 - 527, может быть выражено как

  • [0-4], за которыми следуют две произвольные цифры или
  • 5, за которыми следует 00 - 27 (что разрешается рекурсивно!)

Диапазоны на фигуре 1000 - abcd и abcd - 9999 такие же простые.

Нижний предел, верхний предел различной длины.

Если номер "from" короче номера "to", то он довольно прямой.

Предположим, например, что номер from имеет 3 цифры, а номер to имеет 7 цифр. Выражение может быть составлено следующим образом:

  • from - 999 (как описано выше),
  • Любой 4, 5 или 6 значный номер: [1-9][0-9]{3-5} или
  • 1000000 - to (как описано выше)

Нижний предел / верхний предел равной длины.

Это самая сложная ситуация (но не , хотя хитрая!)

Решение, опять же, лучше всего описано на примере. Рассмотрим диапазон 273 - 548. Выражение может быть составлено из следующих частей:

  • 2, за которыми следуют 73 - 99 (последняя часть описана выше),
  • [34], за которыми следуют любые две цифры или
  • 5 и 00 - 48 (последняя часть описана выше)
1 голос
/ 14 июня 2011

Дайте мне посмотреть, правильно ли я это понимаю.У вас есть файл с именем a-NUMBER-b.txt.Вы должны проверить, что номер является правильным номером.Вот как это делается:

Чтобы проверить число, предполагая, что оно в правильном формате:

String name = getName();
int myInt = Integer.parseInt(name.split(a + "-")[1].split("-" + b + ".txt")[0]);

Чтобы проверить формат:

name.startsWith(a + "-") && name.endWith("-" + b + ".txt")

Сообщите мнеесли я правильно ответил, Райан

0 голосов
/ 14 июня 2011

Нечто подобное может сработать, хотя и не уверен в стоимости раскола.

File[] files = new File("foo").listFiles();
for( int i = 0; i < files.length; i++ )
{
    String fn = files[i].getName();
    String sl[] = fn.split( "-" );
    int num = Integer.parseInt( sl[1] );

    if( num >= min && num <= max )
         //do stuff
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...