Php 有效地删除可能不包含特定单词的子字符串-

Php 有效地删除可能不包含特定单词的子字符串-,php,regex,regex-negation,performance,regex-lookarounds,Php,Regex,Regex Negation,Performance,Regex Lookarounds,我尝试用php将一些令人敬畏的无效html代码映射到稍后需要的xml结构。这很有效,但总有一些部分我无法处理。因此,决定是,删除该代码,使xml保持有效。这可能就是它的样子 <body> <item>abc</item> <item>def</item> unparsable rest </body> abc def 不可分解的休息 因此,我们的目标是,找到一个解决方案(可能是regex,但我对

我尝试用php将一些令人敬畏的无效html代码映射到稍后需要的xml结构。这很有效,但总有一些部分我无法处理。因此,决定是,删除该代码,使xml保持有效。这可能就是它的样子

<body>
    <item>abc</item>
    <item>def</item>
    unparsable rest
</body>

abc
def
不可分解的休息
因此,我们的目标是,找到一个解决方案(可能是regex,但我对任何解决方案都持开放态度)来删除“不可解析的rest”

我试着用这个正则表达式替换preg_

/<\/item>(((?!item).)*)\s*<\/body>/iU
/((?!item)。*)*)\s*/iU
它工作得很好,完全匹配了我想要的1美元的部分,所有的东西都在最后和最后之间,但是由于XML非常大,计算在几毫秒后就崩溃了。我知道regex在做消极前瞻方面做得不太好,但我不认为它有那么糟糕

因此,需要一个更有效的解决方案。不幸的是,我不能使用strrpos,因为在regex模式中有一个后有更多的标记。它的速度很慢,请参阅我链接到的答案中的“性能问题”部分

因此,您当前的正则表达式,我更喜欢在不使用
U
的情况下编写,并且使用
s
修饰符作为
~(((?!item)。*?)\s*?~是

注意这里的
\s*
\s*?
没有太大的语义差异,因为在
之前没有其他量化模式<代码>\s*
,贪婪模式,在这种情况下是首选

让我们用
[^i]*(?:i(?!tem)[^i]*)替换模式并替换
(((?!item)。)*?
~([^i]*(?:i(?!tem)[^i]*)*)\s*~是

这仍然是相当多的字符串。
之后的空格可以与
\s*+
进行占有式匹配,以减少对该字符串部分的回溯访问。
~\s*+([^i]*(?:i(?!tem)[^i]*)\s*~is
显示了改进,现在与字符串匹配,并且只有
不可解析的rest
位于组1值中

不幸的是,我们不能在这里进行太多的回溯操作,因为您希望从组1值中删除尾随空格


如果要匹配
之间所有内部不包含
的内容,则模式将类似于
~\s*+([^检查每一行以“”开头:

$t=
abc
def
不可分解的休息
';
//把绳子分成几行
$filtered=array\u filter(分解(“\n”,$t),函数($line){
//每行
$line=trim($line);//忽略空格
返回$line[0]='';
});
//重建字符串
$result=内爆(“\n”,$filtered);
回声$结果;

演示:

过于简化,您可以检查
*?但解析器可能无法解析无效内容,这正是我的问题:)还有
*?我不是说什么开箱即用,我是说你最好编写一个解析器。你之前提到过这是一个转换的结果。上一个转换听起来好像需要处理,而不是它失败的地方的创可贴。如果你告诉我一个HTML解析器,它可以处理
文本
(这是一个很好的错误)我会接受:)但是loadHtml()根本没有机会。我实际上写了很多我会出错的解析规则,但在某个时候,一个页面只需要20个小时。所以决定删除其余的。