Я хочу выполнить split() для строки, используя регулярное выражение в Java, но хотел бы сохранить разделенные маркеры в массиве [дубликат]


На этот вопрос уже есть ответ здесь:

Как я могу отформатировать свое регулярное выражение, чтобы разрешить это?

Вот регулярное выражение: "\b[(\w'\-)&&[^0-9]]{4,}\b"

Он ищет любое слово, состоящее из 4 букв и более.

Если я хочу разделить, скажем, статью, я хочу массив, который включает все разделенные значения, плюс все ценности между ними, все в том порядке, в котором они первоначально появились. Так, например, если я хочу разделить следующее предложение: "мне нужно купить новый автомобиль. Я бы предпочел БМВ.", мой желаемый результат от разделения будет следующим, где выделенные курсивом значения являются разделителями.

"я", "нуждаюсь" , "чтобы", "купить" , "новый", "автомобиль ",". Я", "хотел бы", " ", "предпочитаю ", " БМВ."

Итак, все слова с >4 символами являются одним маркером, в то время как все, что находится между каждым разделенным значением, также является одним маркером (даже если это несколько слов с пробелами). Я буду только изменять разделенные значения и хотел бы сохранить все остальное таким же, включая пробелы, новые строки и т. д.

Я прочитал в другом потоке, что я мог бы использовать lookaround, чтобы заставить это работать, но я не могу правильно его отформатировать. Возможно ли вообще заставить это работать так, как мне бы хотелось?

2 3

2 ответа:

Я не уверен, что вы пытаетесь сделать, но на всякий случай, если вы хотите изменить слова, которые имеют по крайней мере четыре буквы, вы можете использовать что-то вроде этого (он изменит слова с =>4 буквами на свою версию в верхнем регистре)

String data = "I need to purchase a new vehicle. I would prefer a BMW.";
Pattern patter =  Pattern.compile("(?<![a-z\\-_'])[a-z\\-_']{4,}(?![a-z\\-_'])",
        Pattern.CASE_INSENSITIVE);
Matcher matcher = patter.matcher(data);

StringBuffer sb = new StringBuffer();// holder of new version of our
                                        // data
while (matcher.find()) {// lets find all words
    // and change them with its upper case version
    matcher.appendReplacement(sb, matcher.group().toUpperCase());
}
matcher.appendTail(sb);// lets not forget about part after last match

System.out.println(sb);

Вывод:

I NEED to PURCHASE a new VEHICLE. I WOULD PREFER a BMW.

Или если вы измените заменяющий код на что-то вроде

matcher.appendReplacement(sb, "["+matcher.group()+"]");

Вы получите

I [need] to [purchase] a new [vehicle]. I [would] [prefer] a BMW.
Теперь вы можете просто разделить такую строку на каждую [ и ], чтобы получить нужный массив.

Предполагая, что" слово " определяется как [A-Za-z], Вы можете использовать это регулярное выражение:

(?<=(\\b[A-Za-z]{4,50}\\b))|(?=(\\b[A-Za-z]{4,50}\\b))

Полный код:

class RegexSplit{
    public static void main(String[] args){
        String str = "I need to purchase a new vehicle. I would prefer a BMW.";
        String[] tokens = str.split("(?<=(\\b[A-Za-z]{4,50}\\b))|(?=(\\b[A-Za-z]{4,50}\\b))");
        for(String token: tokens){
            System.out.print("["+token+"]");
        }
        System.out.println();
    }
}

Чтобы получить этот вывод:

[I ][need][ to ][purchase][ a new ][vehicle][. I ][would][ ][prefer][ a BMW.]