PHP:从引号之间删除重复的单词

时间:2014-04-02 16:24:22

标签: php regex preg-replace

如何从以下字符串中的class =“”之间删除重复项?

<li class="active active"><a href="http://netcoding.net/indev/sample-page/">Sample Page</a></li>

请注意,所显示的课程可以更改并处于不同的位置。

3 个答案:

答案 0 :(得分:7)

您可以使用DOM解析器,然后使用explodearray_unique

$html = '<li class="active active">
         <a href="http://netcoding.net/indev/sample-page/">Sample Page</a></li>';
$doc = new DOMDocument();
libxml_use_internal_errors(true);
$doc->loadHTML($html); // loads your html
$xpath = new DOMXPath($doc);
$nodelist = $xpath->query("//li");
for($i=0; $i < $nodelist->length; $i++) {
    $node = $nodelist->item($i);
    $tok = explode(' ', $node->getAttribute('class'));
    $tok = array_unique($tok);
    $node->setAttribute('class', implode(' ', $tok));
}
$html = $doc->saveHTML();
echo $html;

输出:

<html><body>
<li class="active"><a href="http://netcoding.net/indev/sample-page/">Sample Page</a></li>
</body></html>

Online Demo

答案 1 :(得分:2)

使用正则表达式,您可以使用lookbehind和lookahead来查找重复项:

$pattern = '/(?<=class=")(?:([-\w]+) (?=\1[ "]))+/i';

这将替换序列中捕获组1 ([-\w]+)的多个实例。

$str = '<li class="active active">';

echo preg_replace($pattern, "", $str);

输出

<li class="active">

Test at regex101


编辑08.04.2014

删除不在lookbehind (?<=class=") ...

之后的重复项

问题是,后视断言只能是固定长度的。所以像(?<=class="[^"]*?)这样的东西是不可能的。作为替代\K could be used,它重置比赛的开始。模式可以是:

$pattern = '/class="[^"]*?\K(?<=[ "])(?:([-\w]+) (?=\1[ "]))+/i';

您可以将\K之前的所有内容想象为可变长度的虚拟后视。

这个正则表达式作为第一个正则表达式,只会替换序列中一个副本的多个实例。


编辑11.09.2014

最后,我认为单个正则表达式会删除所有不同的重复项,这一点变得相当复杂:

/(?>(?<=class=")|(?!^)\G)(?>\b([-\w]++)\b(?=[^"]*?\s\1[\s"])\s+|[-\w]+\s+\K)/

这个使用continuous matching,很快找到class="

Test at regex101;另请参阅SO Regex FAQ

使用正则表达式的更简单方法是preg_replace_callback()

$html = '<li class="a1 a1 li li-home active li li active a1">';

$html = preg_replace_callback('/\sclass="\K[^"]+/', function ($m) {
  return trim(implode(" ",array_unique(preg_split('~\s+~', $m[0]))));
}, $html);

请注意older PHP-versions don't support anonymous functions(如果是,请更改为正常功能)。

答案 2 :(得分:1)

一种方法是将这些值添加到数组中并过滤它们。以下是它的制作方法。

<?php
   preg_match_all('/class="([A-Za-z0-9 ]+)"/',$htmlString, $result);
   $classes = explode(" ",$result[0]);
   $classes = array_unique($classes);
   echo "<li class=\"".implode(" ",$classes)."\"><a href=\"http://netcoding.net/indev/sample-page/\">Sample Page</a></li>";
?>