Регулярное выражение для сопоставления списка точных строк с некоторыми переменными символами

#java #regex

Вопрос:

Я ищу способ сопоставить список параметров, которые включают некоторые предопределенные символы и некоторые переменные символы, используя String#matches метод Java. Например:

Возможный параметр 1: abc;[variable lowercase letters with maybe an underscore]

Возможный Параметр 2: cde;[variable lowercase letters with maybe an underscore]

Возможный параметр 3: g;4

Пример 1: abc;erga_sd,cde;dfgef,g;4

Пример 2: g;4,abc;dsfaweg

Пример 3: cde;df_ger

Каждый из параметров будет разделен запятыми, но они могут располагаться в любом порядке и включать 1, 2 и/или 3 (без дубликатов).

Это регулярное выражение, которое у меня есть до сих пор, частично работает: (abc;[a-z_,] ){0,1}|(cde;[a-z,] ){0,1}|(g;4,){0,1}

Проблема в том, что он также находит что-то вроде этого допустимым: abc;dsfg,dfvser где начало строки после запятой не начинается с допустимого abc; или cde; или g;4

Комментарии:

1. Почему вы думаете, что регулярное выражение-это инструмент, который вам нужен?

Ответ №1:

Как вы сказали:

Проблема в том,что он также находит что-то вроде этого допустимого: abc;dsfg, dfvser, где начало строки после запятой не начинается с допустимого abc; или cde; или g;4

Поэтому допустимые записи всегда будут иметь шаблоны после запятой. Что вы можете сделать, так это разделить все входные данные разделителем "," и применить допустимый шаблон регулярного выражения к разделенным элементам, а затем объединить результаты сопоставления разделенных элементов, чтобы получить результат сопоставления всей входной строки.

Ваше регулярное выражение должно быть:

 (abc;[a-z_] )|(cde;[a-z_] )|(g;4)
 

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

Вот код:

 String regex = "(abc;[a-z_] )|(cde;[a-z_] )|(g;4)";
boolean finalResult = true;
for (String input: inputList.split(",")) {
    finalResult = finalResult amp;amp; Pattern.matches(regex,input);
}
System.out.println(finalResult);
 

Ответ №2:

Если вы хотите использовать совпадения, то вся строка должна совпадать.

 ^(?:(?:abc|cde);[a-z_] |g;4)(?:,(?:(?:abc|cde);[a-z_] |g;4))*$
 

Объяснение

  • ^ Начало строки
  • (?: Группа без захвата
    • (?:abc|cde);[a-z_] совпадение или abc; или cde; и 1 символов a-z или _
    • | Или
    • g;4 Совпадение буквально
  • ) Закрыть группу без захвата
  • (?: Группа без захвата
    • ,(?:(?:abc|cde);[a-z_] |g;4) Поставьте запятую и повторите первый шаблон
  • )* Закройте группу без захвата и при необходимости повторите
  • $ Конец строки

Смотрите демонстрацию регулярных выражений и демонстрацию Java

Пример кода

 String[] strings = { 
        "abc;erga_sd,cde;dfgef,g;4",
        "g;4,abc;dsfaweg",
        "cde;df_ger",
        "g;4",
        "abc;dsfg,dfvser"
};

String regex = "^(?:(?:abc|cde);[a-z_] |g;4)(?:,(?:(?:abc|cde);[a-z_] |g;4))*$";
Pattern pattern = Pattern.compile(regex);

for (String s : strings) {
    Matcher matcher = pattern.matcher(s);
    if (matcher.matches()) {
        System.out.printf("Match for %s%n", s);
    } else {
        System.out.printf("No match for %s%n", s);
    }
}
 

Выход

 Match for abc;erga_sd,cde;dfgef,g;4
Match for g;4,abc;dsfaweg
Match for cde;df_ger
Match for g;4
No match for abc;dsfg,dfvser
 

Если не должно быть никакого дубликата abc; cde , или g;4 вы можете исключить это, используя отрицательный внешний вид с обратной ссылкой, чтобы дважды соответствовать одному и тому же в начале шаблона.

 ^(?!.*(abc;|cde;|g;4).*1)(?:(?:abc|cde);[a-z_] |g;4)(?:,(?:(?:abc|cde);[a-z_] |g;4))*$
 

Демонстрация регулярных выражений