Regex не жадные чередования - PullRequest
1 голос
/ 03 апреля 2019

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

Пример: проверить эту строку моего текстового файла

123;456;789

с 3 различными выражениями

1.*;.*;..9
3.*;.*;787
.2.;.*;..9

и сделайте что-нибудь, когда шаблоны соответствуют или не соответствуют каждому.Поэтому мне нужно знать, какой из моих шаблонов соответствует или нет в этом примере: только P1 и P3 совпадают, поэтому я выполняю действие 1 и действие 3 на входе 123;456;789

Наивное решение с вложенным циклом for даетплохая производительность (из-за алгоритма).

пример:

for(String row : rows){
   for (Pattern p : patterns){
     if(p.matcher(value).matches()){
       //
     }
   }
}

Я думал о встраивании нескольких регулярных выражений с помощью "|"оператор

, используя приведенный выше пример: (1.*;.*;..9)|(3.*;.*;787)|(.2.;.*;..9)

String expression = "(1.*;.*;..9)|(3.*;.*;787)|(.2.;.*;..9)";
String value = "123;456;789";
Pattern  pattern = Pattern.compile(expression);
Matcher matcher = pattern.matcher(value);

HashMap<Integer,Boolean> results= new HashMap<>();
if(matcher.matches()) {
    int count = matcher.groupCount();
    for (int i = 1; i <= count; ++i) {
        results.put(i, matcher.group(i) != null);
    }
}

Но двигатель останавливается при первом подходящем варианте

Есть ли способ проверить несколько различных шаблонов водин звонок?Иначе как я могу улучшить алгоритм, не будучи квадратичным

Ответы [ 2 ]

1 голос
/ 03 апреля 2019

Это правильное поведение движка регулярных выражений, чтобы останавливаться там, где найдено успешное совпадение. Чтобы смоделировать то, что вы пытаетесь сделать, вы должны работать со сторонними наблюдателями, но таким образом, чтобы они не прерывали матч (скорый провал или скоро успех). Итак, что-то вроде следующего регулярного выражения будет пытаться сопоставить три разные группы захвата. Если не удается найти соответствие одному регулярному выражению внутри групп захвата, так как это не является обязательным, пробуется другой запрос, и это продолжается до конца:

^(?=(1.*;.*;..9$)?)(?=(3.*;.*;787$)?)(?=(.2.;.*;..9$)?)

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

if (capturingGroup == 1) {
    // do something
} else if (capturingGroup == 2) {
...

См. живое демо здесь (здесь два ваших регулярных выражения сопоставлены и узнаваемы)

Примечание : Вы можете удалить точечные звезды в пользу более ограничительного паттерна. В настоящее время это соответствует так много.

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

^(?:(?=(1.*;.*;..9$)?)(?=(.2.;.*;..9$)?)|(3.*;.*;787)$)
0 голосов
/ 03 апреля 2019

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

(?=(1.*;.*;..9))(3.*;.*;787)|(.2.;.*;..9)

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

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