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
(подчеркивания заменить на пробелы здесь, чтобы сделать объяснение более ясным):
- первый матч:
the_
, оставшуюся строку:cat_in_the_hat
- второй матч:
_in_
, оставшуюся строку:the_hat
-
the
не соответствует, так как ему не предшествует пробел ни в начале (исходной) строки.
вы могли бы использовать lookarounds, поскольку они ведут себя как условия (т. е. if
):
(?<=^| )(?:the|and|at|in|or|on|off|all|beside|under|over|next)(?= |$)
таким образом, вы бы:
- первый матч:
the
, оставшуюся строку:_cat_in_the_hat
- второй матч:
in
, оставшуюся строку:_the_hat
- третий матч:
the
, оставшуюся строку:_hat
но @JonathanMee ответ является лучшим решением, так как границы слов были реализованы точно для этой цели;)