Php 预匹配标记之间的文本,不包括中间的相同标记

Php 预匹配标记之间的文本,不包括中间的相同标记,php,html,regex,tags,pcre,Php,Html,Regex,Tags,Pcre,我知道有几个类似的问题,但在这个具体案例中找不到任何问题 我使用了一个代码并根据自己的需要进行了调整,但现在我发现了一个无法纠正的错误 代码: 其结果是: <namespace key="1">Talk" Talk” 这是因为数字和“和”字母被认为是在单词边界内。我怎样才能解决这个问题呢?这可能不是理想的答案,但我正在搞乱一个正则表达式生成器: <?php # URL that generated this code: # http://txt2re.com/index-p

我知道有几个类似的问题,但在这个具体案例中找不到任何问题

我使用了一个代码并根据自己的需要进行了调整,但现在我发现了一个无法纠正的错误

代码:

其结果是:

<namespace key="1">Talk"
Talk”

这是因为数字和“和”字母被认为是在单词边界内。我怎样才能解决这个问题呢?

这可能不是理想的答案,但我正在搞乱一个正则表达式生成器:

<?php
# URL that generated this code:
# http://txt2re.com/index-php.php3?s=%3Cnamespace%3E%3Cnamespace%20key=%22-2%22%3EMedia%3C/namespace%3E&12&11

$txt='arstarstarstarstarstarst<namespace key="-2">Media</namespace>arstarstarstarstarst';

$re1='.*?'; # Non-greedy match on filler
$re2='(?:[a-z][a-z]+)'; # Uninteresting: word
$re3='.*?'; # Non-greedy match on filler
$re4='(?:[a-z][a-z]+)'; # Uninteresting: word
$re5='.*?'; # Non-greedy match on filler
$re6='(?:[a-z][a-z]+)'; # Uninteresting: word
$re7='.*?'; # Non-greedy match on filler
$re8='((?:[a-z][a-z]+))';   # Word 1

if ($c=preg_match_all ("/".$re1.$re2.$re3.$re4.$re5.$re6.$re7.$re8."/is", $txt, $matches))
{
    $word1=$matches[1][0];
    print "($word1) \n";
}

#-----
# Paste the code into a new php file. Then in Unix:
# $ php x.php
#-----
?>

这一行正是我需要的

   $tag_ini = "<{$tag}\\b[^>|^\\/>]*>"; $tag_end = "<\\/{$tag}>";
$tag_ini=“| ^\\/>]*>”$tag_end=“”;

非常感谢@Alison和@Wictor的帮助和指导

主要问题是在开头标记后没有使用单词边界,因此模式中的
名称空间
也可以匹配
名称空间
标记和其他许多标记

随后的问题是,如果有一个自动关闭的
名称空间
标记,后跟一个“正常”成对的打开/关闭
名称空间
标记,则
]*>(.*)
模式将过火。因此,您需要在
(请参阅)之前使用负前瞻
(?![^>]*\/>)
\b
之后使用负前瞻(请参阅)

所以,你可以使用

$tag_ini = "<{$tag}\\b[^>]*(?<!\\/)>"; $tag_end = "<\\/{$tag}>";
$tag_ini=“]”*(?”;$tag_end=“”;

当前正在尝试:$tag\u regex='/'.$tag\u ini。“[^{$tag\u ini}]*?”.$tag_end.'/si';如果你投反对票,你可以解释为什么这不是一个好问题,但是为了一个好的描述和一个片段,当你试图用正则表达式处理XML时,可能会对这个问题投更多的反对票。至于为什么你会得到名称空间标签,你没有使用单词边界:
$tag_ini=“]*>”;
。但是,这并不能解决嵌套标记的问题,您需要一个。不过,您最好使用DOM解析来解析标记之间的内容。我正在处理碰巧包含XML的标记转储,而不是html本身。我将尝试学习递归正则表达式,感谢您的帮助tip@WiktorStribiżew如果你作为答案发布,我将接受它,因为它导致了解决方案现在,这是一个非常有用的链接。但我正在处理输出,所以我需要其他东西。我认为这对我删减短语的较大文本不起作用,这种情况是在解析文档。如果您发布更多文档,这会有所帮助。我的意思是,任何带有嵌套标记的文本都适合测试抱歉,我意识到链接是在.ZIM格式的,我会尝试找到原始的,但是你得到了要点。编辑:这里有一个与我一起工作的格式相同的链接,OK是XML,但是我工作的大部分内容不使用标签,这就是为什么我认为ReX在DOM上为这个字符字符类把符号看作是独立的单位,因此,你的代码>[^>|^\\/>]
不正确(它匹配任何字符,而不是
^
/
。我认为|就像一个“或”操作符:x
在字符类外是一个交替操作符。在字符类内,它是一个文字管道符号。对不起,但我很难理解。Regex对我来说就像中文:(你的意思是,如果有,下一个将包含在上一个中,就像在bug示例中一样?但这和其他的一样工作:?我遗漏了一些东西?你能在演示中设置我的失败和你的失败的地方,以便我能看到差异吗?我感谢你的耐心你的正则表达式不允许在任何tag内容。它不匹配任何非
/>
的文本。若要匹配任何非
/>
的文本,您需要一个类似
(?:(?!\/>)*
或展开的令牌:
[^\/]*(?:\/(?!>)[^\/*)*
我觉得正则表达式太复杂了。如果您同意,让我们来解决这个用例的问题,完成后我会尝试理解原因。如果没有,我会不知所措。如果我简化我的,请使用\\b[^>\/]*>,这行得通吗?在我的测试中,它似乎确实行得通。因此,将所有内容都设置为>或/。对吗?请看一看。不正确的正则表达式可能是危险的,在某些情况下有效,但在某些情况下,它将失败。您只需知道何时以及使用哪些内容。
   $tag_ini = "<{$tag}\\b[^>|^\\/>]*>"; $tag_end = "<\\/{$tag}>";
$tag_ini = "<{$tag}\\b[^>]*(?<!\\/)>"; $tag_end = "<\\/{$tag}>";