preg_match 仅在找到时显示替换
preg_match only show replacement if found
标题一定很混乱,但我不得不承认,当谈到正则表达式时,我也是。我的问题如下:
我有一个输入字符串:
{a href=www.google.com}Google{/a} {b}boldText{/b}
我想要实现的是:
<a href="www.google.com">Google</a> <b>boldText</b>
我有以下 preg_replace 功能:
$input = preg_replace('/\{(\/)?'.$tag.'( [a-z]*\=)?([a-zA-Z0-9\.\:\/]*)?\}/', '<'.$tag.' "">', $input);
标签是f.e。 a
或 b
或 script
。到目前为止,代码是有效的,唯一的问题是没有任何属性的标签是这样的:
<a href="www.google.com">Google</a> <b "">boldText</b>
我能否以某种方式在 preg_match
函数的替换参数中围绕 ""
添加一个 if
条件,如果可以,我该怎么做?
我将 2 个可选组合并为 1 个并使用第二个 preg_replace
在开始标记内的属性值周围添加双引号。我们不能一次性完成,因为具有属性的标签的替换模式不同。
$input = preg_replace('/\{(\/)?'.$tag.'( [a-z]*\=[a-zA-Z0-9\.\:\/]*)?\}/', '<' . $tag . '>', $input);
<?php
$tag = "a";
$str = "{a href=www.google.com at=val}Google{/a} {b}boldText{/b}";
$input = preg_replace('#\{(\/)?' . $tag . '\b((?:\s+[a-z]*\=[a-zA-Z0-9\.\:\/]*)*)\}#', '<' . $tag . '>', $str);
$result = preg_replace("#(?:(<".$tag.")\b|(?<!^)\G)(\s*[^\s=>]+?)=([^=>\s]*)(?=.*?>)#", "=\"\"", $input);
echo $result;
输出:<a href="www.google.com" at="val">Google</a> {b}boldText{/b}
preg_replace_callback
允许使用替换函数而不是字符串。这使您能够进行有条件的替换:
$temp = '{a href=www.google.com}Google{/a} {b}boldText{/b}';
$pattern = <<<'EOD'
~
{ (?<close>/)? (?<tag>\w+)
(?: # optional attribute part
\s+ (?<attribute>\w+)
(?: # optional attribute value
\s* = \s*
# works even if it is already quoted:
(?| " (?<value> [^"]* ) " # " # <-- these comments are only here
| ' ([^']*) ' # ' # for the SO highlighter
| ([^}\s]*)
)
)?
)?
\s* }
~x
EOD;
$result = preg_replace_callback($pattern, function ($m) {
if ($m['close'])
return '</' . $m['tag'] . '>';
if (isset($m['attribute'])) {
return '<' . $m['tag'] . ' ' . $m['attribute']
. (isset($m['value']) ? '="' . $m['value'] . '">' : '>');
}
return '<' . $m['tag'] . '>';
}, $temp);
echo $result;
优点:字符串只被解析一次,因为模式不关心它是什么类型的标签 (*) 以及它是否具有属性。解析器对语法(尤其是空格和最终引号)的容忍度相对较高。
不方便:没有检查模板语法。 (所有标签都被替换,包括非封闭标签或孤立的封闭标签。)
(*) 如果需要,您可以轻松地将一组允许的标签传递给回调函数,为什么不将一个包含每个标签的允许属性的多维数组传递给回调函数。
标题一定很混乱,但我不得不承认,当谈到正则表达式时,我也是。我的问题如下:
我有一个输入字符串:
{a href=www.google.com}Google{/a} {b}boldText{/b}
我想要实现的是:
<a href="www.google.com">Google</a> <b>boldText</b>
我有以下 preg_replace 功能:
$input = preg_replace('/\{(\/)?'.$tag.'( [a-z]*\=)?([a-zA-Z0-9\.\:\/]*)?\}/', '<'.$tag.' "">', $input);
标签是f.e。 a
或 b
或 script
。到目前为止,代码是有效的,唯一的问题是没有任何属性的标签是这样的:
<a href="www.google.com">Google</a> <b "">boldText</b>
我能否以某种方式在 preg_match
函数的替换参数中围绕 ""
添加一个 if
条件,如果可以,我该怎么做?
我将 2 个可选组合并为 1 个并使用第二个 preg_replace
在开始标记内的属性值周围添加双引号。我们不能一次性完成,因为具有属性的标签的替换模式不同。
$input = preg_replace('/\{(\/)?'.$tag.'( [a-z]*\=[a-zA-Z0-9\.\:\/]*)?\}/', '<' . $tag . '>', $input);
<?php
$tag = "a";
$str = "{a href=www.google.com at=val}Google{/a} {b}boldText{/b}";
$input = preg_replace('#\{(\/)?' . $tag . '\b((?:\s+[a-z]*\=[a-zA-Z0-9\.\:\/]*)*)\}#', '<' . $tag . '>', $str);
$result = preg_replace("#(?:(<".$tag.")\b|(?<!^)\G)(\s*[^\s=>]+?)=([^=>\s]*)(?=.*?>)#", "=\"\"", $input);
echo $result;
输出:<a href="www.google.com" at="val">Google</a> {b}boldText{/b}
preg_replace_callback
允许使用替换函数而不是字符串。这使您能够进行有条件的替换:
$temp = '{a href=www.google.com}Google{/a} {b}boldText{/b}';
$pattern = <<<'EOD'
~
{ (?<close>/)? (?<tag>\w+)
(?: # optional attribute part
\s+ (?<attribute>\w+)
(?: # optional attribute value
\s* = \s*
# works even if it is already quoted:
(?| " (?<value> [^"]* ) " # " # <-- these comments are only here
| ' ([^']*) ' # ' # for the SO highlighter
| ([^}\s]*)
)
)?
)?
\s* }
~x
EOD;
$result = preg_replace_callback($pattern, function ($m) {
if ($m['close'])
return '</' . $m['tag'] . '>';
if (isset($m['attribute'])) {
return '<' . $m['tag'] . ' ' . $m['attribute']
. (isset($m['value']) ? '="' . $m['value'] . '">' : '>');
}
return '<' . $m['tag'] . '>';
}, $temp);
echo $result;
优点:字符串只被解析一次,因为模式不关心它是什么类型的标签 (*) 以及它是否具有属性。解析器对语法(尤其是空格和最终引号)的容忍度相对较高。
不方便:没有检查模板语法。 (所有标签都被替换,包括非封闭标签或孤立的封闭标签。)
(*) 如果需要,您可以轻松地将一组允许的标签传递给回调函数,为什么不将一个包含每个标签的允许属性的多维数组传递给回调函数。