使用 preg replace 删除锚标记后的空格
Removing spaces after anchor tag with preg replace
我想在锚标记后放置一个 space,以便下一个单词与其分开。问题是锚标签后面有
个字符,或者可能还有另一个 html 标签开头。所以在那些情况下我们不想放 space
因为它会打破我们的记录。
我只想把space放在anchor后面,如果没有space而且有一个词。
现在我想出了正则表达式,我不确定这正是我想要的
preg_replace("/\<\/a\>([^\s< ])/", '</a> ', $text, -1, $count);
print "Number of occurence in type $type = $count \n";
$this->count += $count;
在实际保存替换字符串之前,我试图查看出现次数。但它显示出更高的数量,我非常怀疑这不可能。
请帮我修正这个正则表达式。
场景:
<a href="blah.com">Hello</a>World // Here we need to put space between Hello and World
<a href="blah.com">Hello</a> World // Do not touch this
<a href="blah.com">Hello</a><b>World</b> // do not touch this
可能有很多情况需要忽略,但具体来说我们需要执行第一个场景
正如@trincot 指出的那样,[^\s< ]
并不意味着 如果它不是 space 或不间断的 space。这是一个字符 class ,括号之间的任何内容都只有一个字符的平均值。所以这意味着 如果它不是 space
或 <
或 &
或...
您需要检查下一个字符是否是表示 [a-zA-Z0-9_]
的单词字符 \w
,然后考虑添加一个 space 在零宽度断言中使用的正向前看:
preg_replace("~</a>\K(?=\w)~", ' ', $text, -1, $count);
echo "Number of occurrences in type $type is $count \n";
这个 RegEx 是什么意思?
</a> # Match closing anchor tag
\K # Reset match
(?=\w) # Look if next character is a word character
更新:涵盖所有HTML问题案例的另一种解决方案:
preg_replace("~</a>\K(?! )~", ' ', $text, -1, $count);
当关闭锚标签后没有不间断space时,这会添加一个不间断space。
您可以使用:/(?<=<\/a>)(\w+)/g
正则表达式
含义:找到以结束锚标签为前缀的单词并替换为space和第一个捕获组引用($1)
您可能会发现,正则表达式解决方案迟早会被证明是不够的。例如,它不会检测到在这个 HTML 片段中显示的两个单词之间没有白色 space:
<a>test</a><span>hello</span>
在许多其他情况下,正则表达式解决方案很难像这样检测相邻的词,因为 HTML 的呈现并不像看起来那么简单。
虽然您已经接受了一个解决方案,但我在此提供一个解决方案,该解决方案使用 PHP 中可用的 DOMDocument 界面来检测 link 文本在何处会粘附在后面的文本上它,即使它在 DOM 节点层次结构中与它远程分离:
function separateAnchors($html) {
// Define a character sequence that
// will certainly not occur in your document,
// and is interpreted as literal in regular expressions:
$magicChar = "²³²";
$doc = new DOMDocument();
$doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($doc);
$anchors = $xpath->query("//a");
foreach (array_reverse(iterator_to_array($anchors)) as $anchor) {
$parent = $anchor->parentNode;
$origAnchor = $anchor->cloneNode(true);
// temporariy put the special text in the anchor
$anchor->textContent = $magicChar;
// and then take the document's text content
$txt = $doc->textContent;
// If that contains the special text with a non-space following it:
if (preg_match("/{$magicChar}\S/u", $txt)) {
// ... then add a single space node after it, after
// any closing parent nodes
$elem = $anchor;
while (!$elem->nextSibling) $elem = $elem->parentNode;
$elem->parentNode->insertBefore($doc->createTextNode(" "),
$elem->nextSibling);
}
// Put original anchor back in place
$parent->replaceChild($origAnchor, $anchor);
}
return $doc->saveHTML();
}
// sample data
$html = "<p><a>first link</a> <a>second link</a>this word is too close</p>\n
<table><tr><td><a>table cell</a></td></tr></table><span>end</span>\n
<span><a>link</a></span><span><a>too close</a></span>";
// inject spaces
$html = separateAnchors($html);
// Show result
echo $html;
上查看 运行
我想在锚标记后放置一个 space,以便下一个单词与其分开。问题是锚标签后面有
个字符,或者可能还有另一个 html 标签开头。所以在那些情况下我们不想放 space
因为它会打破我们的记录。
我只想把space放在anchor后面,如果没有space而且有一个词。
现在我想出了正则表达式,我不确定这正是我想要的
preg_replace("/\<\/a\>([^\s< ])/", '</a> ', $text, -1, $count);
print "Number of occurence in type $type = $count \n";
$this->count += $count;
在实际保存替换字符串之前,我试图查看出现次数。但它显示出更高的数量,我非常怀疑这不可能。
请帮我修正这个正则表达式。
场景:
<a href="blah.com">Hello</a>World // Here we need to put space between Hello and World
<a href="blah.com">Hello</a> World // Do not touch this
<a href="blah.com">Hello</a><b>World</b> // do not touch this
可能有很多情况需要忽略,但具体来说我们需要执行第一个场景
正如@trincot 指出的那样,[^\s< ]
并不意味着 如果它不是 space 或不间断的 space。这是一个字符 class ,括号之间的任何内容都只有一个字符的平均值。所以这意味着 如果它不是 space
或 <
或 &
或...
您需要检查下一个字符是否是表示 [a-zA-Z0-9_]
的单词字符 \w
,然后考虑添加一个 space 在零宽度断言中使用的正向前看:
preg_replace("~</a>\K(?=\w)~", ' ', $text, -1, $count);
echo "Number of occurrences in type $type is $count \n";
这个 RegEx 是什么意思?
</a> # Match closing anchor tag
\K # Reset match
(?=\w) # Look if next character is a word character
更新:涵盖所有HTML问题案例的另一种解决方案:
preg_replace("~</a>\K(?! )~", ' ', $text, -1, $count);
当关闭锚标签后没有不间断space时,这会添加一个不间断space。
您可以使用:/(?<=<\/a>)(\w+)/g
正则表达式
含义:找到以结束锚标签为前缀的单词并替换为space和第一个捕获组引用($1)
您可能会发现,正则表达式解决方案迟早会被证明是不够的。例如,它不会检测到在这个 HTML 片段中显示的两个单词之间没有白色 space:
<a>test</a><span>hello</span>
在许多其他情况下,正则表达式解决方案很难像这样检测相邻的词,因为 HTML 的呈现并不像看起来那么简单。
虽然您已经接受了一个解决方案,但我在此提供一个解决方案,该解决方案使用 PHP 中可用的 DOMDocument 界面来检测 link 文本在何处会粘附在后面的文本上它,即使它在 DOM 节点层次结构中与它远程分离:
function separateAnchors($html) {
// Define a character sequence that
// will certainly not occur in your document,
// and is interpreted as literal in regular expressions:
$magicChar = "²³²";
$doc = new DOMDocument();
$doc->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
$xpath = new DOMXPath($doc);
$anchors = $xpath->query("//a");
foreach (array_reverse(iterator_to_array($anchors)) as $anchor) {
$parent = $anchor->parentNode;
$origAnchor = $anchor->cloneNode(true);
// temporariy put the special text in the anchor
$anchor->textContent = $magicChar;
// and then take the document's text content
$txt = $doc->textContent;
// If that contains the special text with a non-space following it:
if (preg_match("/{$magicChar}\S/u", $txt)) {
// ... then add a single space node after it, after
// any closing parent nodes
$elem = $anchor;
while (!$elem->nextSibling) $elem = $elem->parentNode;
$elem->parentNode->insertBefore($doc->createTextNode(" "),
$elem->nextSibling);
}
// Put original anchor back in place
$parent->replaceChild($origAnchor, $anchor);
}
return $doc->saveHTML();
}
// sample data
$html = "<p><a>first link</a> <a>second link</a>this word is too close</p>\n
<table><tr><td><a>table cell</a></td></tr></table><span>end</span>\n
<span><a>link</a></span><span><a>too close</a></span>";
// inject spaces
$html = separateAnchors($html);
// Show result
echo $html;
上查看 运行