регулярное выражение для условия if в Java - PullRequest
1 голос
/ 28 февраля 2012

так что у меня есть эта проблема .. ОПРОС, сопровождаемый комбинацией 10 As, Ds или Ms (согласен, не согласен, возможно), сопровождаемый да или нет.Если ответ отрицательный, должна быть указана следующая причина.

Захватите ff:

  • Ответы A, D, M
  • Да/ нет ответа
  • [Причина, по которой следует нет]

// без учета регистра

я пришел к этому регулярному выражению

 POLL\s+([ADM]{10})\s+(yes|no\s+([a-z. ]+))

Строка: POLL admaaadddm no no comment

Вывод:

combination --> admaaadddm
yes or no --> no no comment  //this should be fix, it must capture no only
reason --> no comment

мой код:

    String message = "POLL admaaadddm no no comment";

    Pattern pattern = Pattern.compile("POLL\\s+([ADM]{10})\\s+(yes|no\\s+([a-z. ]+))"
            ,Pattern.CASE_INSENSITIVE);


    Matcher m = pattern.matcher(message);

    try
    {
        if (m.matches())
        {

            String combination = m.group(1);
            String yesno = m.group(2);
            String reason = m.group(3);

            System.out.println(combination);
            System.out.println(yesno);
            System.out.println(reason);

        }
    }
    catch (NullPointerException e)
    {
    }

Ответы [ 5 ]

0 голосов
/ 28 февраля 2012

Вы можете поместить условное выражение в свое регулярное выражение с предвидением.

Pattern.compile("POLL\\s+([ADM]{10})\\s+((?=no)(no)\\s(.+$)|yes$)", Pattern.CASE_INSENSITIVE);

Это не будет соответствовать строке, содержащей комментарий после «да», и не будет соответствовать «нет» без комментария. Используйте группы 1, 3 и 4 с «нет» и 1 и 2 с «да».

** РЕДАКТИРОВАТЬ **

Следующее регулярное выражение должно работать, и результаты будут храниться в правильных группах. 1, 2 и 3 (используйте группу 4, если вам нужна «причина» без начального пробела).

Pattern pattern = Pattern.compile("POLL\\s+([ADM]{10})\\s+(no|yes$)((?:(?<=yes)($)|\\s+(.*)))", Pattern.CASE_INSENSITIVE);
0 голосов
/ 28 февраля 2012

Ваша проблема в том, что третья группа захвата вложена во вторую, поэтому причина будет зафиксирована как в группе 2, так и в группе 3. Попробуйте переместить скобки от конца регулярного выражения до сразу после 'no', то есть POLL\s+([adm]{10})\s+(yes|no)\s+([a-z. ]+).

Если группа 2 равна "да", просто игнорируйте все, что соответствует группе 3, предполагая, что там что-то есть.

Редактировать

Хорошо, попробуйте это POLL\s+([adm]{10})\s+(yes|no)(?:(?<=no)([a-z. ]+)|$) RegExr

Нет без причины не должно совпадать, и да не должно с причиной.Группы захвата тоже постоянны, то есть группа 2 всегда фиксирует да / нет, группа 3 всегда фиксирует причину.

0 голосов
/ 28 февраля 2012

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

(?:...) группа без захвата.

 POLL\s+([ADM]{10})\s+(?:yes|(no)\s+([a-z. ]+))

Обновление

Тогда я думаю, что вам нужно пойти на что-то вроде этого:

POLL\s+([ADM]{10})\s+(?:(yes)|(no)\s+([a-z. ]+))

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

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

Таким образом, вам нужно проверить, действительны ли group[2] или group[3]. Если group[3], то есть также group[4] с комментарием.

group[1] всегда содержит часть ADM

group[2] содержит "да", если есть "да", иначе NULL

group[3] содержит "нет", если есть "нет", иначе NULL

group[4] содержит "комментарий", если он есть, в противном случае NULL

0 голосов
/ 28 февраля 2012

Попробуйте POLL\s+([ADM]{10})\s+((yes|no)(\s+([a-z. ]+))?) - мы добавляем новую группу для (yes|no). Его номер будет 3, а группа причины - 5. Вы сопоставляете необязательный текст после yes, но игнорируете его, что, я думаю, должно быть в порядке.

EDIT:

Вставив знак доллара $ после yes, вы предотвратите совпадение, если после yes: POLL\s+([ADM]{10})\s+((yes$|no)(\s+([a-z. ]+))?)

РЕДАКТИРОВАТЬ 2 (в ответ на @TristanDiaz):

Я бы не стал ставить на это свою жизнь, но боюсь, то, что вы желаете, невозможно, по крайней мере, с помощью стандартного регулярного выражения. С одной стороны, вы хотите, чтобы no и объяснения после него всегда собирались вместе. Это означает объединение в регулярном выражении. С другой стороны, вы хотите захватить только yes или no в одну из ваших групп, для чего необходимо как-то разбить строку no после строки. Вы не можете иметь это обоими способами одновременно. Вам нужно будет либо сделать что-то за пределами регулярного выражения (например, захватить no и текст после него в одну группу и разделить его с помощью обычных строковых функций вне регулярного выражения), либо выбрать группу захвата, из которой нужно взять да / нет текста в зависимости от условия. В любом случае вам нужен внешний код.

Регулярные выражения имеют определенную выразительную силу, и не все могут быть выражены с их помощью. Например, такие простые выражения, как «n A-символов, за которыми следуют n B-символов» или «арифметическое выражение с правильными вложенными скобками», невозможно выразить с помощью регулярных выражений.

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

0 голосов
/ 28 февраля 2012

это работает?

Pattern pattern = Pattern.compile("POLL\\s+([adm]{10})\\s+(yes|no)\\s+([a-z. ]+)"
            ,Pattern.CASE_INSENSITIVE);

затем получить группу (1,2, 3 ).

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