В Java вы можете использовать что-то вроде
String s = "Jean-Pierre bought \"blue-green-red\" product-2345 and other blue-red stuff. yellow-black-white. product_a-b";
StringBuffer result = new StringBuffer();
Matcher m = Pattern.compile("(\"[^\"]*\")|\\b([a-zA-Z]+)-(?=[a-zA-Z]+\\b)").matcher(s);
while (m.find()) {
if (m.group(1) != null) {
m.appendReplacement(result, m.group(0));
} else {
m.appendReplacement(result, m.group(2) + " ");
}
}
m.appendTail(result);
System.out.println(result.toString());
// => Jean Pierre bought "blue-green-red" product-2345 and other blue red stuff. yellow black white. product_a-b
См. Демо Java .
Регулярное выражение:
("[^"]*")|\b([a-zA-Z]+)-(?=[a-zA-Z]+\b)
Подробности
("[^"]*")
- Группа 1: "
, 0+ символов, отличных от "
и "
|
- или \b
- граница слова - ([a-zA-Z]+)
- группа 2: 1+ букв (может быть заменена на (\p{L}+)
для соответствия любой букве) -
- дефис (?=[a-zA-Z]+\b)
- положительный прогноз, который, непосредственно справа от текущего местоположения, требует 1+ букв и границы слова.
Если группа 1 соответствует (if (m.group(1) != null)
), вы простовставить матч обратно в результат.Если нет, вставьте обратно значение группы 2 и пробел.
Добавление сюда clojure кода из вопроса тоже для лучшей наглядности:
(def s "Jean-Pierre bought \"blue-green-red\" product-2345 and other blue-red stuff. yellow-black-white. product_a-b"
(defn append [[g1 g2 g3]] (if g2 g1 (str g3 " ")))
(clojure.string/replace s #"(\"[^\"]*\")|\b([a-zA-Z]+)-(?=[a-zA-Z]+\b)" append)
;;=> "Jean Pierre bought \"blue-green-red\" product-2345 and other blue red stuff. yellow black white. product_a-b"