Я хотел бы знать, можно ли использовать один набор шаблонов поиска / замены регулярных выражений для замены всех вхождений определенного символа внутри строки, содержащейся в 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)
Вам может потребоваться уточнить это, если период может произойти сразу после открытия токена и / или непосредственно перед закрывающим токеном, и вы не хотите их заменять.