PHP正则表达式解析避免子字符串

PHP正则表达式解析避免子字符串,php,regex,Php,Regex,我正在编写一个简单的Markdown解析器,为同样使用一些LaTeX公式的页面输出HTML。例如,对于斜体字: //斜体 $content=preg\u replace\u回调( '/(\*|_)(.+)\1/', 功能(百万美元){ 返回“$m[2]”; }, $content ); 不幸的是,许多标记格式与LaTeX符号(以及代码块)冲突,因此我需要首先转义LaTeX部分,并仅在这些部分之外解析标记。LaTeX位由$和$$分隔,因此很容易发现它们: preg\u匹配(“/\$+(.*?\$

我正在编写一个简单的Markdown解析器,为同样使用一些LaTeX公式的页面输出HTML。例如,对于斜体字:

//斜体
$content=preg\u replace\u回调(
'/(\*|_)(.+)\1/',
功能(百万美元){
返回“$m[2]”;
},
$content
);
不幸的是,许多标记格式与LaTeX符号(以及代码块)冲突,因此我需要首先转义LaTeX部分,并仅在这些部分之外解析标记。LaTeX位由
$
$$
分隔,因此很容易发现它们:

preg\u匹配(“/\$+(.*?\$+/”,$content)
例如,这是这样一个页面的示例:


##章节标题
Lorem ipsum*dolores*sic amet$E=mc^2$,自:
$$
\cos(3*\pi*\sqrt{2})=\delta
$$
所以…斜体和乘法之间的冲突

我的第一个猜测是我应该将内容分成两个数组:一个包含带索引的LaTeX位,另一个包含位于LaTeX位之间的非LaTeX位,将第二个数组放在一边,然后将它们合并在一起

preg_split()。似乎可以使用
PREG_SPLIT_DELIM_CAPTURE
标志来调整它,以返回所有子字符串,包括与regexp匹配的断点,但是文档没有显示使用此标志时的输出数据结构,因此我不知道如何迭代输出数组,只处理与模式不匹配的部分


此函数输出什么和/或是否有更好/更快的方法在与其他模式匹配的区域之外执行模式检测?

一个选项可能是使用SKIP FAIL使同一行上仅以
$
开头和结尾的部分不成为匹配的一部分

然后在捕获组中捕获
*
,并使用反向引用
\1
匹配相同的字符,而不匹配中间的相同字符

^\$+(?:\R(?!\$+$).*)*\R\$+$(*SKIP)(*FAIL)|([*_])((?:(?!\1).)+)\1
模式匹配:

  • ^
    字符串的开头
  • \$+
    匹配1+次出现的
    $
  • (?:\R(?\$+$).*)
    匹配所有不只有
    $
  • \R\$+$
    仅将行与
    $
    匹配
  • (*跳过)(*失败)|
    跳过当前匹配的内容
  • ([*.])
    组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;
$content=

对于那些不熟悉您的LaTEX起始文档的人,您应该显示示例数据。非常感谢,这非常有帮助!
## 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)