Java Regex, REGEX_ИГНОРИРОВАТЬ_РЕГИСТР, ЛИТЕРАЛ плюс полное слово

Вопрос или проблема

Я пытаюсь удалить/заменить целые слова в строке.

Я хотел бы сделать это нечувствительно к регистру, и это также должно работать для специальных символов, таких как .,\ или /.

Для этого я использую следующий код:

String result = Pattern.compile(stringToReplace, Pattern.LITERAL | Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher(inputString)
                    .replaceAll("");

Таким образом, это работает для специальных символов, и это нечувствительно к регистру.

Я знаю, что я могу включить сопоставление целых слов, использовав “\b”.

Я мог бы сделать следующее:

String result = Pattern.compile("\\b"+stringToReplace+"\\b",  Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher(inputString)
                    .replaceAll("");

Таким образом, это будет сопоставлять только целые слова, но будут проблемы со специальными символами. Это мешает Pattern.LITERAL. Мне нужно отключить это, что нежелательно.

Как я могу комбинировать Pattern.LITERAL с сопоставлением целых слов?

Вы должны помнить, что \b шаблон границ слов зависим от контекста и соответствует между началом/концом строки и символом слова или между словом и несловарным символом.

Вам нужно использовать

String result = Pattern.compile("(?!\\B\\w)"+Pattern.quote(stringToReplace)+"(?<!\\w\\B)",  Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE).matcher(inputString)
                    .replaceAll("");

Есть два основных изменения:

  • stringToReplace нужно Pattern.quote в кавычки, чтобы убедиться, что все специальные символы экранированы
  • Адаптивные границы слов обеспечат, чтобы граница слова требовалась только тогда, когда это необходимо, т.е. когда соседние символы являются символами слова. (?!\B\w) является левосторонней адаптивной границей слова, а (?<!\w\B) является правосторонней адаптивной границей слова. На самом деле, кажется, что оба могут использоваться взаимозаменяемо из-за природы нулевых утверждений ширины и шаблона границы слова, но эта нотация лучше с логической точки зрения.

Ответ или решение

Чтобы выполнить замену целых слов в строке с использованием регулярных выражений на языке Java, с учетом особенностей, таких как регистронезависимость и наличие специальных символов, необходимо применять определенные приемы.

Задача

Ваша задача заключается в том, чтобы заменить целые слова в строке. Заменяемое слово должно обрабатываться без учета регистра и корректно реагировать на специальные символы, такие как . или \, которые могут входить в состав строки для замены.

Текущая реализация

Вы уже описали использование Pattern.compile с флагами Pattern.LITERAL и Pattern.CASE_INSENSITIVE. Однако, как вы заметили, эти флаги не позволяют эффективно реализовать требование о целостной замене слова с использованием манипуляции крайними символами.

Проблематика

Использование \b для задания границ слов не работает должным образом вместе с Pattern.LITERAL, так как \b предполагает использование символов, определяемых как «слово». Ваша основная проблема заключается в том, что вам нужно объединить возможность обработки специальных символов и искать только целые слова.

Решение

Вместо комбинации флагов, вы можете использовать следующий подход:

  1. Замените stringToReplace с помощью Pattern.quote, чтобы гарантировать экранирование всех специальных символов.
  2. Используйте адаптивные границы слов, чтобы специфицировать условия, при которых выполняется соответствие только целым словам.

Пример реализации может выглядеть так:

String result = Pattern.compile(
    "(?!\\B\\w)" + Pattern.quote(stringToReplace) + "(?<!\\w\\B)", 
    Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE
).matcher(inputString).replaceAll("");

Объяснение:

  1. Pattern.quote(stringToReplace): Это гарантирует, что все специальные символы в stringToReplace будут экранированы, и вы избежите нежелательного поведения.

  2. Адаптивные границы слов:

    • (?!\\B\\w): Это предикативное выражение (negative lookahead), которое проверяет, что перед stringToReplace нет символа слова, что предотвращает частичное совпадение на конце слова.
    • (?<!\\w\\B): Это предикативное выражение (negative lookbehind), которое проверяет, что после stringToReplace также не стоит символ слова.

Заключение

Таким образом, вы можете точно настроить условие для замены целых слов в строке, не отказываясь от поддержки специальных символов. Использование адаптивных границ слов позволяет вам гарантировать, что манипуляция выполняется только на полных словах, что является вашим приоритетом.

Этот подход обеспечит идеальное соответствие вашим требованиям. Не забывайте тестировать ваше регулярное выражение на различных примерах, чтобы убедиться, что оно работает как ожидается в разных случаях.

Оцените материал
Добавить комментарий

Капча загружается...