有以下一行:
$str = '<div class="hello"> Hello world < hello world?! </div>';
需要查找标签内的所有匹配项,同时避免匹配属性值。试试这样写:
$pattern = '/(.*)(hello)(.*)(?=<'/)/ui';
$replacement = '$1<span style="background:yellow">$2</span>$3';
但是只有一个"你好"。该怎么办?
(*跳过)(*)语法在Perl和PCRE (PHP, Delphi, R…)
尽管有关于使用regex解析html的所有免责声明,但我们可以使用一个令人惊讶的简单regex:<[^>]*>(*SKIP)(*F)|(hello)
示例PHP代码:
$replaced = preg_replace('~<[^>]*>(*SKIP)(*F)|(hello)~i',
'<span style="background:yellow">$1</span>',
$yourstring);
在regex演示中,请参见底部的替换。
这个问题是本问题中解释的"regex匹配模式,不包括…"技术的经典案例。
左侧的|
匹配完整的<tags>
,然后故意失败,之后引擎跳到字符串中的下一个位置。右侧捕获hello
(对第1组不区分大小写),我们知道它们是正确的,因为它们与左侧的表达式不匹配。
- 如何匹配(或替换)模式,除了s1, s2, s3…
- 关于匹配模式的文章,除非…
将文本匹配换行到另一个元素中是一个非常基本的操作,尽管代码有些棘手:
$html = <<<EOS
<div class="hello"> Hello world < hello world?! </div>
EOS;
$dom = new DOMDocument;
$dom->loadHTML($html);
$search = 'hello';
foreach ($dom->getElementsByTagName('div') as $element) {
foreach ($element->childNodes as $node) { // iterate all direct descendants
if ($node->nodeType == 3) { // and look for text nodes in particular
if (($pos = strpos($node->nodeValue, $search)) !== false) {
// we split the text up in: <prefix> match <postfix>
$postfix = substr($node->nodeValue, $pos + strlen($search));
$node->nodeValue = substr($node->nodeValue, 0, $pos);
// insert <postfix> behind the current text node
$textNode = $dom->createTextNode($postfix);
if ($node->nextSibling) {
$node->parentNode->insertBefore($textNode, $node->nextSibling);
} else {
$node->parentNode->appendChild($textNode);
}
// wrap match in an element and insert it
$wrapNode = $dom->createElement('span', $search);
$element = $node->parentNode->insertBefore($wrapNode, $textNode);
}
}
}
}
echo $dom->saveHTML(), "'n";