2009-10-02 80 views
1

我有一个相当长和复杂的HTML文档,我需要找到给定字符串的所有出现,例如, “foobar”,除非它位于<a></a>锚标签之间。正则表达式的挑战 - 在HTML文档中找到“foobar”

问题是:它可能位于锚标记之间的某些文本内,例如,

<a>this is a foobar test</a> 

即使在这种情况下,我应该找到匹配。

我该怎么用一个正则表达式?我不会有麻烦找到<a>foobar</a>等等 - 但要找到每一个“foobar的” 除了时,它的锚标记之间,并通过可能有很多其他的文字环绕似乎有点棘手.....

任何想法??

答:
我们结束了使用这个表达式来解决这个问题 - 万一有人是)好奇,或b)在同一个地方:-)

(?<!\<A.*(?=\<\/A))Test(?!\<\/A.*(?=\<A)) 
+0

作为巴特评论,分析HTML正则表达式的解决方案往往不是失败在某些情况下(嵌入式标签),或者是极其复杂的。考虑使用DOM解析器来查找锚标记中的所有文本,然后对其执行字符串搜索或正则表达式。 – TrueWill 2009-10-02 17:47:46

+0

更正 - 使用DOM搜索未包含在锚标记中的文本节点。 – TrueWill 2009-10-02 17:49:56

回答

2
'foobar(?![^<]*</a>)' 

作品对我来说最简单的情况。它显然不会对a标签中的其他标签产生抵触。

+1

这个问题是它没有考虑到这样的: ASDF foobar的 Chris 2009-10-02 14:32:50

+0

是的,这样的作品,只有当一个标签没有其它标签在其中:“这是一个foobar的foob​​ar test'。 – 2009-10-02 14:34:20

+0

我会说它适用于绝大多数情况。 – SilentGhost 2009-10-02 14:37:48

0

试试这个:

$str = 'foobar <a>this is a foobar <span>foobar</span> test</a> foobar'; 

$pattern = '<a(?:[^"\'>]+|"[^"]*"|\'[^\']*\')*>(?:[^<]+|(?!<\/a\s*>)<)*<\/a\s*>'; 
$parts = preg_split('/('.$pattern.')/', $str, -1, PREG_SPLIT_DELIM_CAPTURE); 
$isLink = (bool) preg_match('/^'.$pattern.'$/', $parts[0]); 
foreach ($parts as &$part) { 
    if (!$isLink) { 
     $part = str_replace('foobar', '!!!found!!!', $part); 
    } 
    $isLink = !$isLink; 
} 
$str = implode('', $parts); 

echo htmlspecialchars($str); 
+0

对不起,愚蠢的问题:这是什么语言/脚本? – 2009-10-02 18:13:51

+0

@marc_s:这是PHP。对不起,我以某种方式假定您要求提供PHP解决方案。 ;-) – Gumbo 2009-10-03 05:59:46

+0

谢谢!不,我在这里处理C#/ .NET/jQuery - 但无论如何感谢 - 我会翻译,看看我能否理解它:-) – 2009-10-03 09:56:04