Java regex заменить все не заменяя все слова

я играл с этим регулярным выражением на Java в течение многих лет и не могу заставить его работать:

(?:^| )(?:the|and|at|in|or|on|off|all|beside|under|over|next)(?: |$)

следующее:

pattern.matcher("the cat in the hat").replaceAll(" ")

дает мне cat the hat. Другим примером ввода является the cat in of the next hat что дает мне cat of next hat.

есть ли способ заставить эту замену регулярных выражений работать без необходимости разбивать их на несколько отдельных регулярных выражений для каждого слова и пытаться заменить строку повторно?

2 ответов


Да, вы можете сделать это довольно легко, вам просто нужно использовать границы, который вы пытаетесь описать с помощью:(?:^| ) просто сделайте это вместо этого:

\b(?:the|and|at|in|or|on|off|all|beside|under|over|next)\b

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

\b(the|and|at|in|or|on|off|all|beside|under|over|next)\b

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

Итак, с вводом the_cat_in_the_hat (подчеркивания заменить на пробелы здесь, чтобы сделать объяснение более ясным):

  1. первый матч: the_, оставшуюся строку: cat_in_the_hat
  2. второй матч: _in_, оставшуюся строку: the_hat
  3. the не соответствует, так как ему не предшествует пробел ни в начале (исходной) строки.

вы могли бы использовать lookarounds, поскольку они ведут себя как условия (т. е. if):

(?<=^| )(?:the|and|at|in|or|on|off|all|beside|under|over|next)(?= |$)

Debuggex Demo

таким образом, вы бы:

  1. первый матч: the, оставшуюся строку: _cat_in_the_hat
  2. второй матч: in, оставшуюся строку: _the_hat
  3. третий матч: the, оставшуюся строку: _hat

но @JonathanMee ответ является лучшим решением, так как границы слов были реализованы точно для этой цели;)