php - PHP regexp 解析避免子字符串
问题描述
我正在编写一个简单的 Markdown 解析器来为也使用一些 LaTeX 方程的页面输出 HTML。例如,对于斜体:
// italic
$content = preg_replace_callback(
'/(\*|_)(.+)\1/',
function ($m) {
return "<i>" . $m[2] . "</i>";
},
$content
);
不幸的是,很多 Markdown 格式与 LaTeX 符号(以及代码块)发生冲突,所以我需要先转义 LaTeX 部分,并仅在这些部分之外解析 Markdown。LaTeX 位由$
and分隔$$
,因此很容易发现它们:
preg_match("/\$+(.*?)\$+/", $content)
例如,这是一个此类页面的示例:
## Section title
Lorem ipsum *dolores* sic amet. $E = mc^2$, and since :
$$
\cos(3*\pi*\sqrt{2}) = \delta
$$
所以……斜体和乘法之间的冲突。
我的第一个猜测是我应该将内容分成 2 个数组:一个包含 LaTeX 位及其索引,一个包含位于 LaTeX 位之间的非 LaTeX 位,处理第二个数组,然后将它们合并在一起。
preg_split()
中断所述模式并返回中间子字符串,但丢弃与模式匹配的子字符串。似乎可以用一个PREG_SPLIT_DELIM_CAPTURE
标志来调整它以返回所有子字符串,包括与正则表达式匹配的断点,但是当使用这个标志时,文档没有显示输出数据结构,所以我不知道如何迭代输出数组,并且仅适用于与模式不匹配的部分。
此函数输出什么和/或是否有更好/更快的方法在与其他模式匹配的区域之外执行模式检测?
解决方案
一种选择可能是$
使用 SKIP FAIL 使仅在同一行上开始和结束的部分不属于匹配项。
然后在捕获组中捕获*
或_
捕获,并使用反向引用\1
来匹配相同的字符,而不匹配其间的相同字符。
^\$+(?:\R(?!\$+$).*)*\R\$+$(*SKIP)(*FAIL)|([*_])((?:(?!\1).)+)\1
模式匹配:
^
字符串的开始\$+
匹配 1+ 次$
(?:\R(?!\$+$).*)*
匹配所有不只有的行$
\R\$+$
只匹配一行$
(*SKIP)(*FAIL)|
跳过当前匹配的内容([*_])
在第 1 组中捕获*
或捕获_
((?:(?!\1).)+)
重复匹配除捕获的字符之外的所有字符\1
对第 1 组的反向引用,匹配与捕获的相同字符
例子
$content= <<<'DATA'
## Section title
Lorem ipsum *dolores* sic amet. $E = mc^2$, and since :
$$
\cos(3*\pi*\sqrt{2}) = \delta
$$
DATA;
$content = preg_replace_callback(
'/^\$+(?:\R(?!\$+$).*)*\R\$+$(*SKIP)(*FAIL)|([*_])((?:(?!\1).)+)\1/m',
function ($m) {
return "<i>" . $m[2] . "</i>";
},
$content
);
echo $content;
输出
## Section title
Lorem ipsum <i>dolores</i> sic amet. $E = mc^2$, and since :
$$
\cos(3*\pi*\sqrt{2}) = \delta
$$
我必须注意,使用正则表达式获取标记可能很脆弱并且有边缘情况。
您可以通过例如断言空白边界来使模式更加具体。
^\$+(?:\R(?!\$+$).*)*\R\$+$(*SKIP)(*FAIL)|(?<!\S)([*_])((?:(?!\1).)+)\1(?!\S)
推荐阅读
- javascript - v-select 同步修饰符将带有 id 的文本从子级传递给父级
- node.js - 如何通过互联网使用 opencv 和 nodejs 捕获内置摄像头?
- ansible - 如何解决:安装 ansible 时请求冲突的问题
- datepicker - 如何在日期字段的焦点上显示日期选择器
- acumatica - 在 Acumatica 中使用销售订单 TR 订单类型
- java - 在 spring security JSessionids 在注销后不会被清除。最初它将在登录页面之前加载
- python - 当我尝试在我的 gnuradio 流程图中导入 python 函数时,我收到消息:“错误的导入语法:”
- blazor - 是否可以在非 .NET 网站中嵌入 Blazor 组件?
- gcc - 是什么导致“x.asm:(.text+0xd): undefined reference to 'y'”?
- excel - 在朋友计算机上加载 VBA 加载项的问题