PHP正则表达式 - 替换但从替换的字符串中获取数值

时间:2016-07-24 23:35:16

标签: php regex preg-replace

我有一些包含多个HTML注释的HTML,每个注释中都有一个表单。我正在尝试使用preg_replace将这些注释和表单替换为[CONTACT_FORM_X]形式的标签,其中X是表单的数字ID。

$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的值,然后使用它代替我在preg_replace中使用X的位置

  2. 我的代码似乎只替换其中一个表单而不是两个表单。如何调整preg_replace以允许多次替换

2 个答案:

答案 0 :(得分: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]解释为我应该保留的唯一内容。

正则表达式演示: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 :(得分:1)

更改您的模式和替换字符串,如下所示:

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

Live demo

工作原理

  • 在括号中加入您想要稍后重复使用的任何文本。这称为捕获的组。所以我在您的模式中将\d更改为(\d+)+只允许两位数+数字)
  • 要从模式中返回第一个捕获的组,请使用\1。将CONTACT FORM END \d更改为CONTACT FORM END \1告诉正则表达式引擎,只要您使用END中显示的相同数字点击START,就会停止要替换的字符串。如果没有这个,引擎会将所有内容替换为最后一个CONTACT FORM END。这就是为什么你只得到一个替代品。
  • 在替换字符串中,使用$1来引用第一个捕获的组。这就是为什么将CONTACT_FORM_X更改为CONTACT_FORM_$1会将正确的数字放在替换字符串中。