Java повторяющегося сопоставления с образцом (3) - PullRequest
2 голосов
/ 16 октября 2011

Я пытаюсь решить простую проблему сопоставления регулярных выражений Java, но все еще получаю противоречивые результаты (в ответ на этот и этот вопрос).

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

Пример такого ввода:

Text group 1_|Text group 2_|||Text group 5_|||Text group 8

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

Чтобы подтвердить, что регулярное выражение работает, я использую RegexPal .

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

1. (?:\||^)([^\\|]*) 
2. \G([^\|]+?)_?\||\G()\||\G([^\|]*)$

Используя любой из них, если я запускаю цикл matcher.find () , я получаю:

  • Все текстовые группы, с подчеркиванием в конце, от Regex 1
  • Все текстовые группы, кроме последней, без подчеркивания, но в конце - две пустые группы из Regex 2.

Таким образом, очевидно, что Regex 2 неверен (и RegexPal также не показывает его как соответствующий).

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

Однако ни одно из двух вышеупомянутых регулярных выражений не возвращает true для matcher.matches () , тогда как matcher.find () всегда верно даже для абсолютно не относящихся к делу входных данных (разумно, поскольку часто будет хотя бы одна подходящая группа, даже в другом тексте).

У меня, таким образом, два вопроса :

  1. Существует ли правильное (полностью работающее) регулярное выражение , исключающее завершающее подчеркивание ?
  2. Есть ли способ проверить, что соответствует только правильное регулярное выражение ?

Код, используемый для тестирования Regex 1, выглядит примерно так:

String input = "Text group 1_|Text group 2_|||Text group 5_|||Text group 8";

Matcher matcher = Pattern.compile("(?:\\||^)([^\\\\|]*)").matcher(input);

if (matcher.matches())
{
    System.out.println("Input MATCHED: " + input);

    while (matcher.find())
    {
        System.out.println("\t\t" + matcher.group(1));
    }

}
else
{
    System.out.println("\tInput NOT MATCHED: " + input);
}

Использование приведенного выше кода всегда приводит к «НЕ СОГЛАСОВАНО». Удаление if / else и только с использованием matcher.find () позволяет получить все текстовые группы .

Ответы [ 2 ]

1 голос
/ 17 октября 2011

RegexPal - это инструмент JavaScript для регулярных выражений.Языки регулярных выражений Java и JavaScript различаются.Рассмотрите возможность использования инструмента Java Regex;возможно этот

Это может быть близко к тому, что вы хотите: (?:([^_\|]+)_{0,1}+\|*)+

Редактировать: Код добавлен.В java 6 это печатает каждую группу (цикл find ()).

public static void main(String[] args)
{
    String input = "Text group 1_|Text group 2_|||Text group 5_|||Text group 8";
    Matcher matcher;
    Pattern pattern = Pattern.compile("(?:([^_\\|]+)_{0,1}+\\|*)+");
    Pattern groupPattern = Pattern.compile("(?:([^_\\|]+)_{0,1}+\\|*)");

    matcher = pattern.matcher(input);
    if (matcher.matches())
    {
        Matcher groupMatcher;

        System.out.println("matcher.matches() is true");
        int groupCount = matcher.groupCount();
        for (int index = 1; index <= groupCount; ++index)
        {
            System.out.print("group (pattern)[");
            System.out.print(index);
            System.out.print("]: ");
            System.out.println(matcher.group(index));
        }

        groupMatcher = groupPattern.matcher(input);
        while (groupMatcher.find())
        {
            System.out.print("group (groupPattern):");
            System.out.println(groupMatcher.group());
                            System.out.println(groupMatcher.group(1));
        }
    }
    else
    {
        System.out.println("No match");
    }
}
1 голос
/ 16 октября 2011

Matcher#matches метод пытается сопоставить всю входную последовательность с шаблоном, поэтому вы получаете результат Input NOT MATCHED.См. Документацию здесь http://download.oracle.com/javase/1.4.2/docs/api/java/util/regex/Matcher.html#matches

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

(?:\\||^)([^\\\\|_]*)

Это сработает, если выуверен, что _ наступает как раз перед |.

...