2009-10-02 4 views
1

У меня довольно длинный и сложный HTML-документ, и мне нужно найти все вхождения данной строки, например. «foobar», если он не находится между <a> и </a> якорных тегов.Regex challenge - найти «foobar» в документе HTML

Беда в том, что она может быть внутри некоторого текста между якорь-тегами, например.

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

и даже в этом случае, я должен не найти матч.

Как это сделать с регулярным выражением ?? У меня не будет проблем с поиском <a>foobar</a> и так далее - но найти все «Foobar» за исключением когда это между тегами якорь и окружен возможной много другой текст кажется немного каверзный .....

Любые идеи ??

ОТВЕТ:
Мы закончили с помощью этого Regex, чтобы решить эту проблему - только в случае, если кто является) любопытным, или б) в том же месте :-)

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

Как прокомментировал Барт, регулярные выражения решения для разбора HTML, как правило, либо не в некоторых случаях (встроенные метки) или быть чрезвычайно сложным. Попробуйте использовать парсер DOM вместо этого, чтобы найти весь текст в тегах привязки, затем выполните строковый поиск или регулярное выражение. – TrueWill

+0

Коррекция - используйте DOM для поиска текстовых узлов, которые не содержатся в тегах привязки. – TrueWill

ответ

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

работает для меня в простейшем случае. он явно не устойчив к наличию других тегов в теге a.

+1

проблема с этим она не принимает во внимание то, как: ASDF Foobar Chris

+0

Да, это работает, только если а-теги не имеют другие теги в них: « это Foobar foobar тест '. –

+0

Я бы сказал, что это работает в подавляющем большинстве случаев. – SilentGhost

1

Вы должны быть способный делать с негативными взглядами и ухабами. Вот хороший учебник:

http://www.regular-expressions.info/lookaround.html

+0

@marc_s: какой это? – SilentGhost

+0

Хорошо, получилось, что он отлично работает с выражением regex '(?

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

Извините, глупый вопрос: какой язык/сценарий? –

+0

@marc_s: Это PHP. Извините, я почему-то предположил, что вы попросили PHP-решение. ;-) – Gumbo

+0

спасибо! Нет, я имею дело с C#/.NET/jQuery здесь, но спасибо в любом случае - я переведу и посмотрю, смогу ли я это понять :-) –