Подтвердить что ты не робот

Как определить, где регулярное выражение не соответствует Java-API

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

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

Можно ли это сделать?

4b9b3361

Ответ 1

Если совпадение не выполняется, то 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

Ответ 2

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

Ответ 3

Вы можете использовать пару вызовов 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
-+++--+++-++-

Ответ 4

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