Regex在<anchor1>和& lt; anchor2>同时忽略任何<>


regex to select between <anchor1> and <anchor2> while ignoring all text inside any <>

我有以下两种类型的文本:

类型一:

<div class="meta-name">Corporate Officers</div>
<div class="meta-data"><table border="0" cellspacing="0" cellpadding="0" width="171">
<col width="171"></col>
<tbody>
<tr height="19">
<td width="171" height="19">Officer One</td>
</tr>
</tbody>
</table> 
</div>
</div>

类型二:

<div class="meta-name">Corporate Officers</div>
<div class="meta-data">Officer Two</div>
</div>
<pre>

我使用php与preg_match_all。我需要一个单一的表达式,从上面返回警官1和警官2。我使用Corporate Officers < /div>作为第一个锚点,< /div>作为第二个锚点,但是我无法在所有的表格胡言乱语中找到Keith Dennis。

我如何在anchor1和anchor2之间返回文本,同时忽略任何括号<>之间的所有文本?

我看到这些线程,但不能使他们的解决方案为我工作:RegEx:提取X之前的所有内容,其中X不在两个括号之间

With SimpleXML:

$xml = new SimpleXMLElement('<div>
    <div class="meta-name">
        Corporate Officers
    </div>
    <div class="meta-data">
        <table border="0" cellspacing="0" cellpadding="0" width="171">
            <col width="171" />
            <tbody>
                <tr height="19">
                    <td width="171" height="19">
                        Officer One
                    </td>
                </tr>
            </tbody>
        </table>
    </div>
</div>
');
$results = array();
foreach($xml->children() as $node) {
    if($node->getName() == 'div') {
        $attributes = $node->attributes();
        $classes = explode(' ', $attributes['class']);
        if(in_array('meta-name', $classes) || in_array('meta-data', $classes)) {
            $results[] = getText($node);
        }
    }
}
function getText($node) {
    $text = trim(sprintf('%s', $node));
    if(strlen($text) !== 0) {
        return $text;
    }
    foreach($node->children() as $child) {
        if($text = getText($child)) {
            return $text;
        }
    }
    return null;
}
var_dump($results);

作为一般的经验法则,永远不要使用Regex来解析HTML

大约80%的正则表达式问题是关于xml/html/xhtml的。大约75%的答案是而不是使用正则表达式。为什么?因为虽然它可能看起来对您的示例有效,但它将是脆弱的,并且可能会随着输入的轻微变化而中断。

请看看这个漂亮的工具。如果您不能使用,请回来,我们将提供帮助。

试试这个regex:

'~<div'b[^>]*>Corporate's+Officers</div>'s*<div'b[^>]*>(?:<(?!/?div'b)[^>]*>|'s+)*'K[^<]+~'

这是基于这样的假设:在开始的<div>标记和您正在寻找的名称之间的HTML中没有其他文本内容。第一部分不言自明:

<div'b[^>]*>Corporate's+Officers</div>'s*<div'b[^>]*>

我假设"Corporate Officers"文本足以定位起点,但如果需要,您可以重新插入class属性。在那之后,

(?:<(?!/?div'b)[^>]*>|'s+)*

…使用除<div></div>标记以外的任意数量的标记,以及任何中间的空白。然后'K出现并说忘记这一切,真正的匹配从这里开始[^<]+消耗到下一个标签开头的所有内容,这就是您在匹配结果中看到的全部内容。就好像'K之前的一切都是积极的回顾,但没有所有的限制。

这里有一个演示