替换"<code>"标记内的所有"\"字符*不*

exh*_*uma 4 php regex latex lookahead lookbehind

首先第一件事情:无论这个,这个,这个也没有这个回答我的问题.所以我会开一个新的.

请阅读

好吧好吧.我知道正则表达式不是解析一般HTML的方法.请注意,创建的文档是使用受限制的受控HTML子集编写的.撰写文档的人都知道他们在做什么.他们都是IT专业人士!

考虑到控制语法它可以解析我在这里使用正则表达式的文件.

我不是试图从网上下载任意文件并解析它们!

而如果分析失败,文档编辑,所以它会解析.我在这里解决的问题比这更普遍(即不替换其他两个模式中的模式).

一点背景(你可以跳过这个...)

在我们的办公室,我们应该"打印"我们的文档.因此,为什么有些人想出把它全部放入Word文档中.到目前为止,我们还没有到那里.而且,如果我完成这项工作,我们可能不需要.

当前状态(......和此)

文档的主要部分存储在TikiWiki数据库中.我创建了一个daft PHP脚本,它将文档从HTML(通过LaTeX)转换为PDF.所选Wiki系统的必备功能之一是WYSIWYG编辑器.正如预期的那样,我们的文档中存在一个不那么正式的DOM.

因此,我使用"简单"正则表达式对文档进行音译.到目前为止,这一切都很好(大部分)都很好,但我遇到了一个我自己还没想到的问题.

问题

一些特殊字符需要替换为LaTeX标记.对于exaple,\角色应该被替换$\backslash$(除非有人知道另一种解决方案?).

除了在一个verbatim街区!

<code>verbatim部分替换标签.但是,如果此code块包含反斜杠(与Windows文件夹名称的情况一样),则脚本仍会替换这些反斜杠.

我估计我可以使用负面LookBehinds和/或LookAheads来解决这个问题.但我的尝试没有奏效.

当然,我会用一个真正的解析器更好.事实上,这是我的"脑内路线图",但它目前已超出范围.该脚本适用于我们有限的知识领域.创建一个解析器需要我从头开始.

我的尝试

示例输入

The Hello \ World document is located in:
<code>C:\documents\hello_world.txt</code>
Run Code Online (Sandbox Code Playgroud)

预期产出

The Hello $\backslash$ World document is located in:
\begin{verbatim}C:\documents\hello_world.txt\end{verbatim}
Run Code Online (Sandbox Code Playgroud)

这是迄今为止我能想到的最好的:

<?php
$patterns = array(
    "special_chars2" => array( '/(?<!<code[^>]*>.*)\\\\[^$](?!.*<\/code>)/U', '$\\backslash$'),
);

foreach( $patterns as $name => $p ){
    $tex_input = preg_replace( $p[0], $p[1], $tex_input );
}
?>
Run Code Online (Sandbox Code Playgroud)

请注意,这只是一个摘录,而且[^$]是另一个LaTeX要求.

似乎有效的另一种尝试:

<?php
$patterns = array(
    "special_chars2" => array( '/\\\\[^$](?!.*<\/code>)/U', '$\\backslash$'),
);

foreach( $patterns as $name => $p ){
    $tex_input = preg_replace( $p[0], $p[1], $tex_input );
}
?>
Run Code Online (Sandbox Code Playgroud)

......换句话说:省略负面的背后.

但这看起来更容易出错,而不是外观和前瞻.

一个相关的问题

您可能已经注意到,该模式是ungreedy(/.../U).那么这个匹配在<code>块内只会尽可能少吗?考虑到环顾四周?

YOU*_*YOU 6

如果我,我将尝试找到HTML解析器并将使用它.

另一种选择是将尝试块串入<code>.*?</code>其他部件.

并将更新其他部分,并将重新组合.

$x="The Hello \ World document is located in:\n<br>
<code>C:\documents\hello_world.txt</code>";

$r=preg_split("/(<code>.*?<\/code>)/", $x,-1,PREG_SPLIT_DELIM_CAPTURE);

for($i=0;$i<count($r);$i+=2)
    $r[$i]=str_replace("\\","$\\backslash$",$r[$i]);

$x=implode($r);

echo $x;
Run Code Online (Sandbox Code Playgroud)

结果如下.

The Hello $\backslash$ World document is located in: 
C:\documents\hello_world.txt
Run Code Online (Sandbox Code Playgroud)

对不起,如果我的方法不适合你.