正则表达式错过了目标字符串的第一次出现

Regular expression missed first occurrence of target string

我在以下 html 代码中使用正则表达式来获取 text1 和 text2。这是我正在使用的: /<div\s?class="right-col">[\s\n\S]*<a[\s\n]?[^>]*>@(.*)<\/a>/ 但显然我错过了 text1,只得到了 text2(这里是 link to my problem)。

<div class="right-col">
    <h1>
        <a href="url-link-here" title="title-here">title1</a>
    </h1>
    <p>some text here</p>
<div class="some-class">
    <div class="left">
        <span><a href="url-link-here" class="breaking" target="_blank">some text here </a></span>      
    </div>
    <div class="postmeta"><a href="url-link-here" >@text1</a> </div>
</div>
<div class="right-col">
    <h1>
        <a href="url-link-here" title="title-here">title2</a>
    </h1>
    <p>some text here</p>
<div class="some-class">
    <div class="left">
        <span><a href="url-link-here" class="breaking" target="_blank">some text here </a></span>      
    </div>
    <div class="postmeta"><a href="url-link-here" >@text2</a> </div>
</div>

你们能告诉我我的正则表达式哪里出了问题吗?有没有更好的方法来捕获 title1, title2 和 text1, text2?

在这里使用正则表达式并不是最好的方法。这是不好的做法。您应该使用 DOM/XML 解析器来执行此操作。

我喜欢用PHP的DOMDocument class. Using XPath,我们可以快速找到你想要的元素

$dom = new DOMDocument;
$dom->loadHTML($html);
$xPath = new DOMXPath($dom);

$aTags = $xPath->query('//div[@class="some-class"]//a[starts-with(text(), "@")]');

foreach($aTags as $a){
    echo $a->nodeValue;
}

演示:http://codepad.viper-7.com/QHOXzH

这是正则表达式的一个相当普遍的问题,因为它们是贪婪的。 [\s\S]*(不需要 \n)匹配第一个 '<' 和 'a',因为它很贪心,所以它会匹配那些并继续。添加一个?让它不贪心并使用你的 link returns text1 和 text2.

简短的回答是将 [\s\n\S]* 替换为 [\s\S]*?但正如其他人所提到的,这可能不是正则表达式的好用法。