Разделение строки в Java: взгляд назад с указанной длиной - PullRequest
0 голосов
/ 15 ноября 2018

Я хочу разбить строку после буквы «K» или «L», кроме случаев, когда за одной из них следует буква «P». Между тем, я надеюсь не разбивать, если длина подстроки меньше 4, когда строка разбивается на месте. Например:

- Input:
AYLAKPHKKDIV

- Expected Output
AYLAKPHK
KDIV

Теперь мне удалось разделить строку после буквы «K» или «L», за исключением случаев, когда за одной из них следует буква «P». Мое регулярное выражение (?<=[K|R])(?!P).

My result:
AYLAKPHK
K
DIV

Однако я не знаю, как игнорировать место разделения, где длина подстроки меньше 4.

Моя демоверсия

Ответы [ 2 ]

0 голосов
/ 15 ноября 2018

Вы можете использовать matcher до совпадение каждой подстроки, а не split, если это возможно - вам может показаться, что логике будет проще следовать, когда вы можете потреблять символов, вместо того, чтобы идентифицировать конкретную позицию . Совпадение трех или более символов, за которыми следует (K или R, за которым не следует P с .{3,}?[KR](?!P), убедитесь, что за ним следуют как минимум 4 символа с (?=.{4}), ИЛИ, если весь вышеприведенный шаблон не выполнен, сопоставьте весь остаток строки с .+$:

String s = "AYLAKPHKKDIV";
List<String> arr = new ArrayList<String>();
Matcher m = Pattern.compile(".{3,}?[KR](?!P)(?=.{4})|.+$").matcher(s);
while(m.find()) {
  arr.add(m.group());
}
0 голосов
/ 15 ноября 2018

Надеюсь не разбить, если длина подстроки меньше 4

Другими словами, вы хотите иметь

  1. предыдущий совпадение (разделение), разделенное на текущий совпадение, по крайней мере, с 4 символами, поэтому ABCKABKKABCD будет разделяться на ABCK|ABKK|ABCD, но не на `ABCK | АБК | .....

  2. не менее 4 символов после текущего разбиения, поскольку ABCKAB после разделения ABCK|AB будет иметь AB в конце, длина которого меньше 4.

Для достижения первого условия вы можете использовать \G, которое представляет место предыдущего совпадения (или начало строки, если совпадений еще нет). Таким образом, первое условие может выглядеть как (?<=\G.{4,}) (ВНИМАНИЕ: обычно предварительный просмотр ожидает очевидную максимальную длину обработчика, который он обрабатывает, но по некоторым причинам здесь работает .{4,}, что может быть ошибкой или добавлением функции в Java 10, которую я сейчас использую В случае, если он жалуется на это, вы можете использовать какое-то очень большое число, которое должно быть больше, чем максимальное количество символов, которое вы ожидаете между двумя разбиениями, например .{4,10000000})

Второе условие проще, поскольку оно просто (?=.{4}).

Кстати, вы не хотите | в [K|R], так как там он представляет литерал, а не оператор ИЛИ, поскольку по умолчанию любой символ в наборе символов является альтернативным выбором. Так что [K|R] представляет K ИЛИ | ИЛИ R. Вместо этого используйте [KR].

DEMO:

String text = "AYLAKPHKKKKKKDIVK123KAB";
String regex = "(?<=[KR])(?!P)(?<=\\G.{4,})(?=.{4})";
for (String s : text.split(regex)){
    System.out.println("'"+s+"'");
}

Выход:

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