PHP正则表达式,错误的html转义导致问题

时间:2010-03-01 12:35:46

标签: php regex

我正在尝试使用(.+?)来隔离以下来源中的“I. NEED.ISOLATION”字样:

<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 个答案:

答案 0 :(得分:3)

请参阅this previous StackOverflow question

也就是说,转义问题是由于内部有/个字符,因为你已经使用/来分隔正则表达式,所以这会让正则表达式解析器感到困惑。

答案 1 :(得分:2)

首先,你真的不应该使用正则表达式来试图“解析”HTML - 这不是很规律。

使用像DOMDocument::loadHTML之类的东西和一些XPath查询通常是一个更好的解决方案。


但是,如果你真的想要使用正则表达式(看起来你好吗,从你的评论到其他答案判断),我想你不应该使用/作为{{3} }:已经有太多的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字符串中不存在的字符,我没有任何东西可以逃脱 - 特别是,我不必逃避所有/ - 这意味着正则表达式要容易得多写作,阅读和理解。

答案 2 :(得分:0)

如果您使用PCRE regular expressions,则需要转义正则表达式中的delimiters(在您的情况下为/):

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

但可能更重要:正则表达式不适合解析HTML。最好使用类似DOMDocument提供的HTML解析器,并使用DOMXPath进行查询。

答案 3 :(得分:0)

$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

答案 4 :(得分:0)

有一个功能可以帮到你。它被命名为 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

答案 5 :(得分:0)

事实上,该字符串中没有任何内容在正则表达式中具有特殊含义(当然,除了(.+?)之外)。 /导致问题的唯一原因是因为您将其用作正则表达式分隔符。您只需选择不同的分隔符,例如~

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