Regex заменить все вхождения одного символа в определенные маркеры

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

Например, можно ли заменить все периоды пробелами для текста между TOKEN1 и TOKEN2, как в примере ниже?

Так что:

TOKEN1:Run.Spot.run:TOKEN2 

изменяется на:

 TOKEN1:Run Spot run:TOKEN2 

ПРИМЕЧАНИЕ. Регулярное выражение должно быть способно заменить любое количество периодов в любом тексте, а не только на определенный шаблон выше.

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

Мне не нравятся обходные пути PHP, поскольку я знаю, как это сделать. Я пытаюсь расширить свои знания о регулярном выражении.

благодаря

Способ сделать это:

 $pattern = '~(?:TOKEN1:|\G(?<!^))(?:[^:.]+|:(?!TOKEN2))*\K\.~'; $replacement = ' '; $subject = 'TOKEN1:Run.Spot.run:TOKEN2'; $result = preg_replace($pattern, $replacement, $subject); 

шаблон детали:

 ~ # pattern delimiter (?: # open a non capturing group TOKEN1: # TOKEN1: | # OR \G(?<!^) # a contiguous match but not at the start of the string ) # close the non capturing group (?: # open a non capturing group [^:.]+ # all that is not the first character of :TOKEN2 or the searched character | # OR :(?!TOKEN2) # The first character of :TOKEN2 not followed by the other characters )* # repeat the non capturing group zero or more times \K # reset the match \. # the searched character ~ # delimiter 

Идея состоит в том, чтобы использовать \G чтобы каждое совпадение было TOKEN1: или совпадение с совпадением прецедентов.

Обратите внимание: поведение по умолчанию похоже на тег html (он всегда открыт до закрытия). Если :TOKEN2 не найден все \. символы будут заменены после TOKEN1:

Я думаю, что лучший способ – написать что-то вроде этого:

 $result = preg_replace_callback( '/(TOKEN1:)([^:]+)(:TOKEN2)/g', function ($matches) { return $matches[0] . preg_replace('/[.]/g', ' ', $matches[1]) . $matches[2]; }, 'TOKEN1:Run.Spot.run:TOKEN2' ); 

(Отказ от ответственности: не проверен.)

В простейшем случае вам понадобится период сбегания ( \ ) (поскольку период обычно совпадает с любым символом) в качестве шаблона: \. , и вы замените его пространством: ,

Это заменит все экземпляры . с ,

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

 (?<=\w)\.(?=\w) 

Для символа слова вам понадобится положительный (нулевой ширины) неподходящий вид: (?<=\w) , ваш экранированный период ( \. ) И положительный (незахватывающий) нулевой размер для символа слова: (?=\w) . Замена этого места будет иметь нужный результат.

Если вы хотите заменить периоды только между токенами, вы можете добавить положительный lookbehind: (?<=TOKEN1:.+) И добавить положительный результат: (? =. + TOKEN2), поэтому полное регулярное выражение будет:

 (?<=TOKEN1:.+)(?<=\w)\.(?=\w)(?=.+TOKEN2) 

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