我有一些类似这样的代码,它用一个链接替换了一些短代码:
$search = array(
'#\{r\|([^|]+)\|([^}]+)\}#',
'#\{t\|([^|]+)\|([^}]+)\}#',
...,
);
$replace = array(
'<a href="/ref/$1">$2</a>',
'<a href="/type/$1">$2</a>',
...,
);
$content = preg_replace( $search, $replace, $content );我有更多类似的preg_replace,所以我想知道,有什么方法可以将它简化为一个带有条件的简单are吗?
例如,使用正则表达式#\{([a-z])\|([^|]+)\|([^}]+)\}#,并根据其字母将第一个匹配项替换为不同的内容(r=ref,t=type)。(如果有帮助,这些短代码类似于{r|url-slug|LinkTitle}。)
发布于 2012-03-07 22:37:46
这需要preg_replace_callback (或者可能只是/e eval修饰符),这将允许您将映射t = type和r = ref放在替换逻辑中:
= preg_replace_callback('#\{([rt])\|([^|]+)\|([^}]+)\}#', "cb_123", ...
function cb_123($m) {
$map = array("t" => "type", "r" => "ref");
$what = $map[ $m[1] ];
return "<a href=\"/$what/$m[2]\">$m[3]</a>";
}发布于 2012-03-07 22:49:01
免责声明:下面的建议很糟糕,并建议使用现在已经被弃用的PHP特性。我只是把它留在这里作为历史参考。
使用公认答案中建议的技巧。
@mario建议的(完全有效的) preg_replace_callback()方法的替代方法是e修饰符,该修饰符仅适用于preg_replace(),并允许将替换字符串作为PHP代码进行计算:
<?php
$shortCodes = array (
'r' => 'ref',
't' => 'type'
);
$expr = '#\{([a-z])\|([^|]+)\|([^}]+)\}#e';
$replace = '"<a href=\"/{$shortCodes[\'$1\']}/$2\">$3</a>"';
$string = 'Some text as a ref {r|link1.php|link} and a type {r|link2.php|link}';
echo preg_replace($expr, $replace, $string);我能想到的唯一问题是,如果您的LinkTitle包含单引号,它将被转义并在输出中显示为\'。
See it working
编辑
经过一些试验和错误之后,这里是一个版本,可以使用任何您可以抛出的东西,还可以在适当的地方通过urlencode()/htmlspecialchars()传递所有数据:
<?php
$shortCodes = array (
'r' => 'ref',
't' => 'type'
);
$expr = array(
'#\{([a-z])\|([^|]+)\|([^}]*"[^}]*)\}#e',
'#\{([a-z])\|([^|]+)\|([^}]+)\}#e'
);
$replace = array(
'"<a href=\"/{$shortCodes[\'$1\']}/".htmlspecialchars(urlencode(\'$2\'))."\">".htmlspecialchars(str_replace(\'\"\', \'"\', \'$3\'))."</a>"',
'"<a href=\"/{$shortCodes[\'$1\']}/".htmlspecialchars(urlencode(\'$2\'))."\">".htmlspecialchars(\'$3\')."</a>"'
);
$string = 'Some text as a ref {r|link &1.php|link&\' with some bad characters in it} and a type {r|link2.php|link with some "quotes" in it}';
echo preg_replace($expr, $replace, $string);输出:
Some text as a ref <a href="/ref/link+%261.php">link&' with some bad characters in it</a> and a type <a href="/ref/link2.php">link with some "quotes" in it</a>
See it working
发布于 2021-06-01 03:55:41
这里的答案更多地是为了说明如何使用标记标签将替换字符串放入模式本身,而不是为了替代@mario (也就是欧洲松鼠)的答案。但如果有人发现这种技术更合适的情况,请让我知道。
标记(*MARK)最初用于确认正则表达式引擎已到达成功模式的路径中的某个位置,但由于可以为其提供标签(*MARK:label),并且此标签在preg_match_all的结果数组中返回...不幸的是,您不能在preg_replace*函数中访问它,这就是为什么您必须匹配整个字符串(即使是替换项不关心的部分),并连接preg_match_all返回的不同匹配结果。
PHP >= 7.4 (用于箭头函数的使用):
$s = 'Other text1 {r|url-slug1|LinkTitle1}
Other text2 {t|url-slug2|LinkTitle2}
Other text3';
$pattern = '~
(?<before> .*? )
{
(?: # you can fill this group with anything you want
r (*MARK:ref)
| t (*MARK:type)
)
\Q|\E (?<url_slug> [^|]+ )
\Q|\E (?<linkTitle> [^}]+ )
}
|
(?<after> .+ )
~xs';
preg_match_all($pattern, $s, $matches, PREG_SET_ORDER);
$res = array_reduce($matches, fn($c, $i) =>
$c . (
$i['after'] ??
$i['before'] . '<a href="/' . $i['MARK'] . '/'
. $i['url_slug']. '">'
. $i['linkTitle'] . '</a>'
)
);
echo $res;https://stackoverflow.com/questions/9603287
复制相似问题