2016-07-24 9 views
0

У меня есть HTML, который содержит несколько комментариев HTML, в каждом комментарии есть форма. Я пытаюсь использовать preg_replace для замены этих комментариев и форм внутри с помощью тега в форме [CONTACT_FORM_X], где X - числовой идентификатор формы.PHP regex - заменить, но получить числовое значение из замещенной строки

$str = 'blah blah blah <!-- CONTACT FORM START [CONTACT_FORM_1] -->some form goes here<!-- CONTACT FORM END 1 --> blah blah blah <!-- CONTACT FORM START [CONTACT_FORM_2] -->another form goes here<!-- CONTACT FORM END 2 -->'; 

$replace = preg_replace('/<!-- CONTACT FORM START \[CONTACT_FORM_\d\] -->.*<!-- CONTACT FORM END \d -->/', '[CONTACT_FORM_X]', $str); 
echo $replace; 

Итак:

<!-- CONTACT FORM START [CONTACT_FORM_1] -->some form goes here<!-- CONTACT FORM END 1 --> 

должны быть полностью заменены с [CONTACT_FORM_1]

И ..

<!-- CONTACT FORM START [CONTACT_FORM_2] --> another form goes here<!-- CONTACT FORM END 2 --> 

должны быть полностью заменены с [CONTACT_FORM_2]

я е я запускаю мой код выше, я получаю:

blah blah blah [CONTACT_FORM_X] 

Так что мои вопросы:

  1. Как я могу получить значение \ d, а затем использовать это в месте, где я в настоящее время использовать X в my preg_replace

  2. Мой код, похоже, заменяет одну из форм, а не обоих вхождений. Как я могу адаптировать preg_replace, чтобы несколько заменяет

ответ

1

preg_replace заменит все вхождения (это глобальный). .* жадный, хотя и соответствует всем после <!-- CONTACT FORM START \[CONTACT_FORM_(\d)\] до <!-- CONTACT FORM END \d -->. Для захвата значения используйте ().

Так попробуйте:

.*?<!-- CONTACT FORM START \[CONTACT_FORM_(\d)\] -->.*?<!-- CONTACT FORM END \d --> 

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

.*?<!-- CONTACT FORM START \[CONTACT_FORM_(\d)\] -->.*?<!-- CONTACT FORM END \1 --> 

Ведущее .*? должно быть удалено, если предыдущее содержимое следует сохранить. Мне непонятно, с чем это связано. Из Should be replaced entirely with [CONTACT_FORM_2] я интерпретировал, что это единственный контент, который должен оставаться.

Regex демо: https://regex101.com/r/kS2nK6/1

PHP Использование:

<?php 
$str = 'blah blah blah <!-- CONTACT FORM START [CONTACT_FORM_1] -->some form goes here<!-- CONTACT FORM END 1 --> blah blah blah <!-- CONTACT FORM START [CONTACT_FORM_2] -->another form goes here<!-- CONTACT FORM END 2 -->'; 

$replace = preg_replace('/.*?<!-- CONTACT FORM START \[CONTACT_FORM_(\d)\] -->.*?<!-- CONTACT FORM END \d -->/', '[CONTACT_FORM_$1]', $str); 
echo $replace; 

PHP Демо: https://eval.in/611232

1

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

$pattern = '/<!-- CONTACT FORM START \[CONTACT_FORM_(\d+)\] -->.*<!-- CONTACT FORM END \1 -->/'; 
$replace = preg_replace($pattern, '[CONTACT_FORM_$1]', $str); 

Live demo

Как это работает

  • Put в круглых скобках любой текст, который вы хотите повторно использовать позже. Это называется захваченной группой. Поэтому я изменил \d на (\d+) в вашем шаблоне (+ просто разрешает двузначные + номера)
  • Чтобы вернуться к первой захваченной группе из шаблона, используйте \1. Изменение CONTACT FORM END \d на CONTACT FORM END \1 сообщает движку регулярных выражений, что строка для замены останавливается, как только вы нажимаете END с тем же номером, который вы видели в START. Без этого двигатель заменяет все на самое последнее CONTACT FORM END. Вот почему вы получили только одну замену.
  • В заменяющей строке используйте $1, чтобы обратиться к первой захваченной группе. Вот почему смена CONTACT_FORM_X на CONTACT_FORM_$1 указывает правильное число в заменяемой строке.
+1

@ chris85 Вы ​​правы. У меня есть. «Должно быть заменено полностью» ссылается на подстроку, которая не включает «бла-бла-бла» (еще раз проверьте ОП) – BeetleJuice

+0

О, неясно, в этом случае. Я также добавлю свой ответ. – chris85

Смежные вопросы