PHP正则表达式难度

时间:2009-05-24 07:07:05

标签: php regex

当文本之间有空格和回车符时,我很难做正则表达式。

例如,在下面这种情况下,如何让正则表达式获得“<div id="contentleft">”?

<div id="content"> 


<div id="contentleft">  <SCRIPT language=JavaScript>

我试过

id="content">(.*?)<SCRIPT

但它不起作用。

6 个答案:

答案 0 :(得分:2)

$s = '<div id="content">

<div id="contentleft">  <SCRIPT language=JavaScript>';

if( preg_match('/id="content">(.*?)<SCRIPT/s', $s, $matches) )
    print $matches[1]."\n";

默认情况下,Dot会匹配除换行符之外的所有内容。 /s使其符合所有内容。

但实际上,使用DOM解析器。您可以遍历树,也可以使用XPath查询。可以把它想象成XML的正则表达式。

$s = '<div id="content">

<div id="contentleft">  <SCRIPT language=JavaScript>';

// Load the HTML
$doc = new DOMDocument();
$doc->loadHTML($s);

// Use XPath to find the <div id="content"> tag's descendants.
$xpath = new DOMXPath($doc);
$entries = $xpath->query("//div[@id='content']/descendant::*");

foreach( $nodes as $node ) {
    // Stop when we see <script ...>
    if( $node->nodeName == "script" )
        break;

    // do what you want with the content
}

XPath非常强大。 Here's some examples.

PS我确信(我希望)上面的代码可以收紧一些。

答案 1 :(得分:1)

查看PCRE修饰符:http://ar2.php.net/manual/en/reference.pcre.pattern.modifiers.php

您可以应用s修饰符,例如'/id="content">(.*?)<SCRIPT/s'(但请注意,因为它会改变^$的工作方式。

否则,您可以执行'/id="content">((.|\n)*?)<SCRIPT/'

编辑:oops,错误的修饰符......

答案 2 :(得分:0)

尝试

id="content">((?:.|\n)*?)<SCRIPT

通常不使用正则表达式解析HTML的警告适用,但您似乎已经知道了。

可替换地:

(?<=id="content">)(?:.|\n)*?(?=<SCRIPT)

默认情况下,点与换行符不匹配。解决这个问题的一种方法是明确允许它们。即使你碰巧使用的正则表达式风格不支持“dotall”修饰符,这也会有效。

第一个正则表达式与您的方法相同,通过允许\n进行扩展。你的比赛将在第1组,你只需要修剪它。

第二个正则表达式使用零宽度断言(前瞻/后瞻)来标记匹配的开始和结束。该比赛不包含任何您不想要的内容,也不需要分组。

答案 3 :(得分:0)

没有正则表达式的另一种解决方案:

$start = 'id="content">';
$end = '<SCRIPT';
if (($startPos = strpos($str, $start)) !== false &&
    ($endPos = strpos($str, $end, $startPos+1)) !== false) {
    $substr = substr($str, $startPos, $endPost-$startPos);
}

答案 4 :(得分:0)

嗯,这是一个多行问题,所以看一下模式修饰符:

  

m(PCRE_MULTILINE)默认情况下,PCRE   将主题字符串视为   由一条“线”组成   字符(即使它实际上   包含几个换行符)。开始   行“元字符(^)匹配   只在字符串的开头,而   “行尾”元字符($)   仅匹配字符串的末尾,   或在终止换行之前   (除非设置了D修饰符)。这是   和Perl一样。

     

设置此修改器后,“开始   行“和”行尾“构造   马上跟着或匹配   紧接在任何新行之前   主题字符串,也分别   在开始和结束时。这是   相当于Perl的/ m修饰符。如果   a中没有“\ n”字符   主题字符串,或者没有出现^   或者在一个模式中,设置这个   修饰符没有效果。

     

s (PCRE_DOTALL)如果此修饰符为   设置,一个点元字符   模式匹配所有字符,   包括换行符。没有它,   新线被排除在外。这个修饰语   相当于Perl的/ s修饰符。一个   负面的类,如[^ a]总是   匹配换行符,   独立于此的设定   改性剂。

来自http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php

答案 5 :(得分:0)

$dom = new DOMDocument();
$dom->strictErrorChecking = false;
$dom->loadHTML($html_str);

$xpath = new DOMXPath($dom);
$div = $xpath->query('div[@id="content"]')->item(0);

请更正我的xpath表达式 - 不确定它是否可行...