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

У меня есть тесты, в которых я проверяю вывод с помощью регулярного выражения. При сбое он сообщает, что вывод X не соответствует регулярному выражению Y.

Я хотел бы добавить указание на то, где в строке совпадение не удалось. Например. что самое большее, что совпадение попало в строку перед возвратом. Matcher.hitEnd() - это один из примеров того, что я ищу, но я хочу что-то более общее.

Возможно ли это сделать?

Ответы [ 4 ]

6 голосов
/ 20 мая 2014

Если совпадение не удается, то Match.hitEnd() сообщает вам, могла ли бы соответствовать более длинная строка.Кроме того, вы можете указать регион во входной последовательности, в котором будет выполняться поиск совпадений.Поэтому, если у вас есть строка, которая не может быть сопоставлена, вы можете проверить ее префиксы, чтобы увидеть, где сбой совпадения:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class LastMatch {
    private static int indexOfLastMatch(Pattern pattern, String input) {
        Matcher matcher = pattern.matcher(input);
        for (int i = input.length(); i > 0; --i) {
            Matcher region = matcher.region(0, i);
            if (region.matches() || region.hitEnd()) {
                return i;
            }
        }

        return 0;
    }

    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("[A-Z]+[0-9]+[a-z]+");
        String[] samples = {
                "*ABC",
                "A1b*",
                "AB12uv",
                "AB12uv*",
                "ABCDabc",
                "ABC123X"
        };

        for (String sample : samples) {
            int lastMatch = indexOfLastMatch(pattern, sample);
            System.out.println(sample + ": last match at " + lastMatch);
        }
    }
}

Вывод этого класса:

*ABC: last match at 0
A1b*: last match at 3
AB12uv: last match at 6
AB12uv*: last match at 6
ABCDabc: last match at 4
ABC123X: last match at 6
3 голосов
/ 08 апреля 2014

Вы можете взять строку и выполнить итерацию по ней, удаляя по одному символу с конца в каждой итерации, а затем проверять наличие hitEnd():

int farthestPoint(Pattern pattern, String input) {
    for (int i = input.length() - 1; i > 0; i--) {
        Matcher matcher = pattern.matcher(input.substring(0, i));
        if (!matcher.matches() && matcher.hitEnd()) {
            return i;
        }
    }
    return 0;
}
1 голос
/ 04 мая 2011

Вы можете использовать пару вызовов replaceAll(), чтобы указать положительное и отрицательное совпадения входной строки. Допустим, например, что вы хотите проверить шестнадцатеричную строку; следующее укажет действительные и недействительные символы входной строки.

String regex = "[0-9A-F]"
String input = "J900ZZAAFZ99X"
Pattern p = Pattern.compile(regex)
Matcher m = p.matcher(input)
String mask = m.replaceAll('+').replaceAll('[^+]', '-')
System.out.println(input)
System.out.println(mask)

Это напечатало бы следующее, с + под действительными символами и - под недопустимыми символами.

J900ZZAAFZ99X
-+++--+++-++-
0 голосов
/ 14 апреля 2011

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

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