2009-11-04 2 views
2

Прежде всего, я знаю, что это плохая практика, и я ответил на многие вопросы, даже если это так сказать, но для уточнения Я вынужден использовать регулярное выражение, потому что это приложение хранит регулярные выражения в базе данных и работает только таким образом. Я абсолютно не могу изменить функциональностьЗахват содержимого внутри html-тегов с регулярным выражением

Теперь, когда мы это убрали, потому что я всегда использую методы DOM, которые я не привык делать с регулярными выражениями.

Я хочу захватить все внутри раздела контента, вплоть до . Первый тег конца div. Мне все равно, будет ли регулярное выражение терпеть неудачу на вложенных div. Мне нужно также захватить символы (новые символы).

<div class="intro-content"> 
<p>blah</p> 
<br/> 
<strong>test</strong> 
</div> 

Regex до сих пор:

<div\s*class="intro-content">(.*)</div> 

Это, очевидно, не работает, потому что . символ не будет соответствовать символы пробела.

Я понимаю, что были заданы сотни вопросов, но на вопросы, которые я посетил, были относительно простые ответы (за исключением ответов на предложения DOM), где (.*) не хватило бы потому, что оно не учитывает новые строки и некоторые регулярные выражения были слишком жадными.

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

ответ

4

Похоже, вам нужно включить флаг «dot all» (s). Это будет сделано. соответствуют всем символам, включая разрывы строк. Например:

preg_match('/<div\s*class="intro-content">(.*)<\/div>/s', $html); 
+0

Ух, не могу поверить, что я это забыл. Спасибо. –

+0

Вы, наверное, забыли больше, чем я когда-либо узнал о регулярном выражении ... :) – Ben

-2

Это, очевидно, не работает, потому что символ . не будет соответствовать символам пробела.

Если делать, но если этого не произойдет, мы можем просто добавить их в:

<div\s*class="intro-content">([ \t\r\n.]*)</div> 

Затем вам нужно, чтобы сделать его ленивым, поэтому он захватывает все вплоть до первого</div> и не последнее. Мы делаем это, добавляя вопросительный знак:

<div\s*class="intro-content">([ \t\r\n.]*?)</div> 

Там. Дайте это выстрел. Возможно, вы сможете заменить пробельные символы (\t\r\n) между [ и ] с одним номером \s.

+1

'.' делает действительно космические символы совпадают, но это не соответствует новым строке символов без использования'/s' модификатора в регулярном выражении. – Bendoh

2

Вы должны не использование регулярных выражений, чтобы разобрать HTML, как это. Теги div могут быть вложенными, и поскольку regexp не имеет никакого контекста, нет возможности проанализировать это. Вместо этого используйте парсер HTML.Например:

$doc = new DomDocument(); 
$doc->loadHtml($html); 
foreach ($doc->getElementsByClassName("div") as $div) { 
    var_dump($div); 
} 

См: DomDocument

Edit:

А потом я увидел ваше примечание:

Я вынужден использовать регулярное выражение, потому что это приложение хранит регулярные выражения в базы данных и работает только так. Я абсолютно не могу изменить функциональность

Хорошо. По крайней мере, убедитесь, что вы соответствуете non-greedy. Таким образом, это будет соответствовать правильно, пока нет вложенных тегов:

preg_match('/<div\s*class="intro-content">(.*?)<\/div>/s', $html); 
+0

Класс DomDocument не имеет метода getElementsByClassName() – Black

Смежные вопросы