Regex не очень хорошо оснащен для этой задачи. Однако вы можете сделать следующее:
- Разделить строку на запятую. Фактически, вы можете разделить запятую, окружив ее любым количеством пробелов, например, в случае, если вы получите
"'abc', 'xyz'"
. Для этого вы можете использовать регулярное выражение \s*,\s*
. - Удалите все, что соответствует строке, которую вы не хотите - вы можете использовать базовое сопоставление строк или регулярное выражение для более сложных шаблонов.
- Преобразоватьснова разделите строку на список, разделенный запятыми.
Использование операций потока Java 8, это может быть коротким:
String[] split = str.split(("\\s*,\\s*")); //1. split into separate strings
String result = Arrays.stream(split) //turn to stream
.filter(chunk -> !"'xyz'".equals(chunk)) //2. remove anything you don't want
.collect(Collectors.joining(",")); //3. convert back to comma separated list
Предикат .filter
можно изменить так, как вам удобно- если вы хотите соответствовать только "'abc'"
, тогда вы можете использовать chunk -> "abc'".equals(chunk)
или .contains
или equalsIgnoreCase
, или даже регулярное выражение.
Возможно, стоит выделить правило фильтра в отдельный предикат, чтобы при необходимости его было легче изменить
Predicate<String> filterRule = chunk -> !"'xyz'".equals(chunk);
/* ... */
.filter(filterRule)
/* ... */
Хотя, если мы рассмотрим это "'xyz'".equals
уже сам по себе предикат, и предикаты могут быть аннулированы, поэтому вам не нужно писать целую лямбду для этого, а просто повторно использовать методы в качестве функциональных интерфейсов:
Predicate<String> stuffWeDontWant = "'xyz'"::equals;
Predicate<String> filterRule = stuffWeDontWant.negate();
Все это может быть встроеноно это немного уродливо, так как вы должны привести его в надлежащий предикат, чтобы отрицать его
Predicate<String> filterRule = ((Predicate<String>) "'xyz'"::equals).negate();
Последняя вещь может выглядеть так:
Predicate<String> filterRule = ((Predicate<String>) "'xyz'"::equals).negate();
String result = Arrays.stream(str.split(("\\s*,\\s*")))
.filter(filterRule)
.collect(Collectors.joining(","));
Так что теперь вы можете большелегко изменить то, что ваше правило фильтра. Вы даже можете повторно использовать это для любого вида списка, просто передавая другой предикат для использования в качестве фильтра.
Не Java 8 или не Stream способ сделать то же самое, чтобы сделать следующее:
String[] split = str.split(("\\s*,\\s*")); //1. split into separate strings
List<String> list = new ArrayList<>(Arrays.asList(split));//convert into an ArrayList to allow removing
list.removeAll(Collections.singleton("'xyz'"));//2. remove anything you don't want
String result = String.join(",", list); //3. convert back to comma separated list
Этот подход все еще можно смешать с использованием предиката с помощью .removeIf()
, но на этот раз он должен точно соответствовать тому, что вам не нужно:
list.removeIf("'xyz'"::equals);
/* or */
list.removeIf("'xyz'"::equalsIgnoreCase);
/* or */
list.removeIf("'xyz'"::startsWith);
/* or */
list.removeIf("'xyz'"::contains);
/* or */
list.removeIf("'xyz'"::endsWith);
/* or */
list.removeIf(Pattern.compile("'(xy?z)*'").asPredicate());
/* ...and so on... */