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

Рассмотрим следующее регулярное выражение:

(([^\|])*\|)*([^\|]*)

Это соответствует шаблонам повторяющихся строк типа

("whatever except |" |) {0 to any times} ("whatever except |" |) {1 time}

Таким образом, он должен соответствовать следующей строке, которая имеет 17 подстрок (16 повторов плюс «z» как последняя).

"abcd  | e | fg | hijk | lmnop | |   | qrs |   t| uv| w |||||x   y|  z"

Действительно, RegexPal проверяет, соответствует ли данное регулярное выражение указанной выше строке.

Теперь я хочу получить каждую из подстрок (т. Е. «Abcd |», «e |», «fg |» и т. Д.), Для которых нет предварительных сведений об их количестве, длине и т. Д.

Согласно предыдущему посту StackOverflow с аналогичным названием и документации Matcher class find(), мне просто нужно сделать что-то вроде

Pattern pattern = Pattern.compile(regex); // regex is the above regex
Matcher matcher = pattern.matcher(input); // input is the above string

while (matcher.find())
{
   System.out.println(matcher.group(1));
}

Однако, когда я делаю это, я просто распечатываю 2 строки: последнюю повторную подстроку ("x y |") и нулевое значение; определенно не те 16 подстрок, которые я ожидаю.

Хорошо бы также проверить, что совпадение действительно произошло , перед запуском цикла find(), но я не уверен, что matches(), groupCount() > 0 или какое-то другое условие следует использовать, не выполняя двойной работы по сопоставлению, учитывая, что find() также выполняет сопоставление.

Итак, вопросов :

  1. Как мне получить все 16 повторяющихся подстрок?
  2. Как мне получить последнюю подстроку?
  3. Как проверить соответствие строки?

Ответы [ 2 ]

4 голосов
/ 08 октября 2011

Боюсь, вы что-то путаете. Всякий раз, когда вы используете повторы ('*', '+' и т. Д.), Вы не можете сопоставить все экземпляры. Используя что-то вроде ((xxx)*), вы можете получить всю строку, совпадающую с group(1), а последнюю часть - group(2), ничего больше.

Рассмотрите возможность использования String.split или лучше Splitter Гуавы .


Объявление 1. Вы не можете. Используйте простой шаблон, такой как

\G([^\|])*(\||$)

вместе с find(), чтобы получить все совпадения в последовательности. Обратите внимание на привязку \G к предыдущему совпадению.


Объявление 2. Как получить последнюю подстроку?

В качестве последнего результата возвращается find.


Объявление 3. Как проверить соответствие строки?

После вашего последнего find проверьте, если matcher.end() == input.length. Но с этим шаблоном вам не нужно ничего проверять, так как он всегда совпадает.

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

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

1) Как я могу получить все 16 повторяющихся подстрок?

Смотри ниже. Когда вы переезжаете на матчи, вам не нужно все, чтобы соответствовать, только тот раздел, который вы хотите. (Я получил 17 матчей - это правильно?)

2) Как я могу получить последнюю подстроку?

Переключение разделителя на начало регулярного выражения, а также разрешение '^'.

3) Как проверить соответствие строки?

Что может претендовать на несоответствие? Любая строка будет соответствовать.

<ч />

Вот решение с использованием регулярных выражений:

String input = "abcd  | e | fg | hijk | lmnop | |   | qrs |   t| uv| w |||||x   y|  z";
int expectedSize = 17;
List<String> expected = new ArrayList<String>(Arrays.asList("abcd  ", " e ", " fg ", " hijk ", " lmnop ", " ", "   ", " qrs ", "   t", " uv", " w ", "",
    "", "", "", "x   y", "  z"));

List<String> matches = new ArrayList<String>();

// Pattern pattern = Pattern.compile("(?:\\||^)([^\\|]*)");
Pattern pattern = Pattern.compile("(?:_?\\||^)([^\\|]*?)(?=_?\\||$)"); // Edit: allows _| or | as delim

for (Matcher matcher = pattern.matcher(input); matcher.find();)
{
  matches.add(matcher.group(1));
}

for (int idx = 0, len = matches.size(); idx < len; idx++)
{
  System.out.format("[%-2d] \"%s\"%n", idx + 1, matches.get(idx));
}

assertSame(expectedSize, matches.size());
assertEquals(expected, matches);

выход

[1 ] "abcd  "
[2 ] " e "
[3 ] " fg "
[4 ] " hijk "
[5 ] " lmnop "
[6 ] " "
[7 ] "   "
[8 ] " qrs "
[9 ] "   t"
[10] " uv"
[11] " w "
[12] ""
[13] ""
[14] ""
[15] ""
[16] "x   y"
[17] "  z"
...