Java regex lookbehind не работает как js regex lookbehind - PullRequest
3 голосов
/ 12 апреля 2020

У меня была эта цель:

Заданная строка: "Part1-part2-part3-part4-part5"
Разделить его при повторном появлении '-',
Так что я ожидаю массив [ "Part1-part2", "part3-part4-part5" ]

Что я сделал:

"Part1-part2-part3-part4-part5".split("(?<=^\\w+-\\w+)-"

Но результат на jdk 8:
Он не находит соответствия 2-ой '-', и возвращает всю строку .
Доказательства: https://ideone.com/myWppm

Но когда я попробовал на веб-сайтах обработки регулярных выражений и node.js (или chrome) [Поверьте мне, современный js поддерживает взгляд позади] результат, как и ожидалось .
Свидетельство: https://ideone.com/ttQWNr

Взлом, который я сейчас использую (не подходит для решения):

Использование Lookahead вместо Lookbehind, 3-е вхождение '-' с конца
"Part1-part2-part3-part4-part5".split("-(?=\\w+-\\w+-\\w+$)");

Ответы [ 3 ]

2 голосов
/ 12 апреля 2020

Java поддерживает конечный вид сзади с использованием квантификатора, например {0,100}

Чтобы сопоставить любой символ, кроме дефиса, вы можете использовать [^-], который является классом отрицательных символов,

Если вы хотите исключить соответствующие новые строки, вы можете расширить его до [^-\\r\\n]

Вы можете использовать:

(?<=^[^-]{0,100}-[^-]{0,100})-

По частям

  • (?<= Положительный взгляд сзади, утверждение, что слева:
    • ^ Начало строки
    • [^-]{0,100} - соответствует 0 - 100 раз любому символу, кроме -, затем соответствует первому -
    • [^-]{0,100} Match 0 - 100 times any char except -`
  • ) Закрыть взгляд назад
  • - Сопоставить второе - с разделить на

Regex demo | Java демо

Например

System.out.println(
    Arrays.toString(
        "Part1-part2-part3-part4-part5".split("(?<=^[^-]{0,100}-[^-]{0,100})-")
    )
);

Выход

[Part1-part2, part3-part4-part5]
1 голос
/ 12 апреля 2020

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

String input = "Part1-part2-part3-part4-part5";
String[] parts = input.split("-(?=[^-]+-[^-]+-[^-]+$)");
System.out.println(Arrays.toString(parts));

Это отпечатки:

[Part1-part2, part3-part4-part5]
1 голос
/ 12 апреля 2020

Вместо использования split() используйте сопоставление:

String input = "Part1-part2-part3-part4-part5";
String regex = "(\\w+-\\w+)-(.*)"
String[] result; // just to simulate result of split()
Matcher m = Pattern.compile(regex).matcher(input);
if (m.matches()) {
    result = new String[] { m.group(1), m.group(2) };
} else {
    result = new String[] { input };
}

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

...