PHP регулярное выражение, некорректное экранирование HTML вызывает проблемы - PullRequest
0 голосов
/ 01 марта 2010

Я пытаюсь использовать (.+?) для выделения слов "I. НЕОБХОДИМОСТЬ. ИЗОЛЯЦИЯ" в приведенном ниже источнике:

<strong>Label:</strong></font></td>
    <td valign="top" width="82%"> <font face="Arial" size="2"> 
      I. NEED. ISOLATION  </font> </td>

используя (.+?), я мог бы сделать это:

$regex = '/stuff before(.+?)stuff after/';

и для этого html это будет:

$regex = '/<strong>Label:</strong></font></td>
    <td valign="top" width="82%"> <font face="Arial" size="2"> 
      (.+?)  </font> </td>/';

но он захлебывается из-за неправильного побега. Я не очень хорош в PHP. Кто-то может посоветовать, пожалуйста, какие символы я должен экранировать на основе HTML, который выглядит следующим образом?

<strong>Label:</strong></font></td>
    <td valign="top" width="82%"> <font face="Arial" size="2"> 
      I. NEED. ISOLATION  </font> </td>

Обратите внимание, что я не пытаюсь создать шаблон регулярного выражения. У меня уже есть шаблон, набитый (.+?), просто нужно знать, как правильно экранировать html, чтобы php не подавился им.

Ответы [ 6 ]

3 голосов
/ 01 марта 2010

См. этот предыдущий вопрос StackOverflow .

Тем не менее, проблема с выходом из-за символов / внутри, которые вводят в заблуждение синтаксический анализатор регулярных выражений, поскольку вы уже используете / es для разделения регулярных выражений.

2 голосов
/ 01 марта 2010

Прежде всего, вам не следует использовать регулярные выражения, чтобы попытаться «разобрать» HTML - что не совсем регулярно.

Если использовать что-то вроде DOMDocument::loadHTML, и некоторые запросы XPath, как правило, являются гораздо лучшим решением.


Но, если вы действительно хотите использовать регулярное выражение (и, судя по вашим комментариям к другим ответам), вы должны использовать / как разделитель регулярных выражений : в HTML уже слишком много сокращений - как вы уже заметили, это будет уходящий ад.

Например, вы можете использовать # в качестве разделителя регулярных выражений:

$str = <<<STR
<strong>Label:</strong></font></td>
    <td valign="top" width="82%"> <font face="Arial" size="2"> 
      I. NEED. ISOLATION  </font> </td>
STR;
$regex = '#<strong>Label:</strong></font></td>
    <td valign="top" width="82%"> <font face="Arial" size="2"> 
      (.+?)  </font> </td>#';
if (preg_match($regex, $str, $m)) {
  var_dump($m[1]);
}

Получит вас:

string 'I. NEED. ISOLATION' (length=18)

Обратите внимание, что единственное, что я изменил по сравнению с вашим предложенным кодом, это разделитель регулярных выражений; -)


И, используя символ, которого нет в строке HTML, мне некуда бежать - особенно мне не нужно экранировать все / s - что означает, что регулярное выражение гораздо проще для обоих пиши, читай и понимай.

0 голосов
/ 04 марта 2010

На самом деле в этой строке нет ничего, что могло бы иметь особое значение в регулярном выражении (кроме, конечно, (.+?)). Единственная причина, по которой / вызывает проблему, заключается в том, что вы используете его как разделитель регулярных выражений. Вам просто нужно выбрать другой разделитель, например ~, например:

$regex = '~<strong>Label:</strong></font></td>
    <td valign="top" width="82%"> <font face="Arial" size="2"> 
      (.+?)  </font> </td>~';
0 голосов
/ 04 марта 2010

Есть функция, которая сделает это за вас. Он называется preg_quote http://pl2.php.net/preg_quote

$regex = '/'.preg_quote('<strong>Label:</strong></font></td>
<td valign="top" width="82%"> <font face="Arial" size="2"> 
  ').'(.+?)'.preg_quote('  </font> </td>).'/';

Вы также должны быть осторожны с чувствительностью к регистру и переносами строк. Я часто добавляю флаги к своим регулярным выражениям, чтобы они выглядели как /(.+?)/is

0 голосов
/ 01 марта 2010
$str=<<<EOF
<strong>Label:</strong></font></td>
    <td valign="top" width="82%"> <font face="Arial" size="2">
      I. NEED. ISOLATION  </font> </td>
EOF;

$s = explode("</font>",$str);
foreach($s as $k=>$v){
    if(strpos($v,'<font face="Arial" size="2">')){
        $t=explode('<font face="Arial" size="2">',$v);
        print trim($t[1])."\n";
    }
}

выход

$ php test.php
I. NEED. ISOLATION
0 голосов
/ 01 марта 2010

Если вы используете регулярные выражения PCRE , вам нужно экранировать разделители внутри регулярного выражения (в вашем случае /):

'/<strong>Label:<\/strong><\/font><\/td>
<td valign="top" width="82%"> <font face="Arial" size="2"> 
  (.+?)  <\/font> <\/td>/'

Но, вероятно, более важно: регулярные выражения не подходят для анализа HTML. Лучше использовать правильный анализатор HTML, например, предоставляемый DOMDocument , и запросить его с помощью DOMXPath .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...