php - PHP 正则表达式替换没有产生预期的结果
问题描述
我正在 PHP 和 MariaDB 中创建一个字典应用程序,并尝试模拟一些基本的降价。当我有这样的定义时:
This is an example definition. Here is a link to [foo]. This is an [aliased link|bar].
然后[foo]
会被翻译成'foo'定义页面[aliased link|bar]
的链接,并且会被翻译成'bar'定义页面的链接。如果有管道,那么管道 (|) 之前的任何内容都将成为链接文本,而管道之后的内容将成为链接目标。如果没有管道,则括号中的表达式将成为链接文本和目标。
所以我会把它翻译成下面的 HTML:
This is an example definition. Here is a link to <a href="foo">foo</a>. This is an <a href="bar">aliased link</a>.
我能想到的最简单的方法是通过两个正则表达式替换。因此,假设我的示例字符串被调用$def
,这是我尝试进行这些替换的代码:
$pattern1 = '/\[(.*?)?\]/m';
$replace1 = '<a href="$1">$1</a>';
$def = preg_replace($pattern1, $replace1, $def);
$pattern2 = '/\[([^]]*?)(?:\|([^]]*?))\]/m';
$replace2 = '<a href="$2">$1</a>';
$def = preg_replace($pattern2, $replace2, $def);
(我认为使用两个正则表达式会更容易,但如果有更简单的一个正则表达式解决方案,我很想知道。)
但是,我显然对正则表达式有问题,因为这是我回显时发生的情况$def
(链接现在只是说明性的,目的地并不重要):
和 HTML:
"This is an example definition. Here is a link to "
<a href="foo">foo</a>
". This is an"
<a href="aliased link|bar">aliased link|bar</a>
"."
谁能建议我需要做些什么来修复正则表达式以获得我想要的结果?我特别困惑,因为当我在www.regex101.com测试这个正则表达式时,它似乎完全按照我的想法做:
我在 Google Chrome 上使用 PHP 7.4.6,带有 XAMPP 和 Apache。
解决方案
Note that in the pattern that you used, you can exclude matching the |
by adding it in the first negated character class to prevent some backtracking. The quantifier for the negated character class also does not have to be non greedy *?
as the ]
can not be crossed at the end.
You could use 2 capture groups where the second group is in an optional part and check for the presence of group 2 using preg_replace_callback.
\[([^][|]+)(?:\|([^][]+))?]
The pattern matches:
\[
Match[
([^][|]+)
Capture group 1, match 1+ times any char except[
]
and|
(?:\|([^][]+))?
Optional non capture group matching|
and capture any char except the listed in group 2]
Match closing]
$pattern = "/\[([^][|]+)(?:\|([^][]+))?\]/";
$s = "This is an example definition. Here is a link to [foo]. This is an [aliased link|bar].";
$s = preg_replace_callback($pattern, function($match){
$template = '<a href="%s">%s</a>';
return sprintf($template, array_key_exists(2, $match) ? $match[2] : $match[1], $match[1]);
}, $s);
echo $s;
Output
This is an example definition. Here is a link to <a href="foo">foo</a>. This is an <a href="bar">aliased link</a>.
推荐阅读
- scala - Scala Spark数据帧过滤器使用基于可用值的多列
- python - 在 Python 3.5 中,IDE 如何将三引号 (""") 视为注释?
- image - Flutter:如何将图像(裁剪)放入下一个有状态/更少的小部件
- r - 在 mutate 中声明变量
- r - ggplot2 - 线条和误差线重叠的问题
- swift - 使用可选类型协议有意义吗?
- amazon-web-services - 如何通过 Terraform 将现有隐私政策附加到 IAM 角色
- debugging - julia LoadError: UndefVarError: @showprogress 未定义
- linux - 如何使用 c 库函数将文本文件的内容打印到 Linux 汇编语言中的 STDOUT?
- browser-cache - 强制从服务器加载图像而不是缓存