在HTML中替换字符串但不包括链接或标题的正则表达式

3
我正在寻找一个正则表达式,用于替换html页面中给定的字符串,但仅当该字符串不是标签本身的一部分或出现在链接或标题文本中时才进行替换。
例如:
查找'replace_me'
<p>You can replace_me just fine</p> OK
<a href='replace_me'>replace_me</a> 不匹配
<h3>replace_me</h3> 不匹配
<a href='/test/'><span>replace_me</span></a> 不匹配
<p style="background:url('replace_me')">replace_me<h1>replace_me</h1></p> 第一个不匹配,第二个OK,第三个不匹配
谢谢!
更新:
我已经找到了一个可行的正则表达式。
\b(replace_me)\b(?!(?:(?!<\/?[ha].*?>).)*<\/[ha].*?>)(?![^<>]*>)

这在正则表达式中可能会很麻烦,但是:(i)使用什么语言?(ii)您是否考虑改用HTML解析器?此外,我认为这可能在XSLT的范围内。 - polygenelubricants
一个 HTML 解析器难道不也会使用正则表达式吗? - Vladimir
1
不,它不是这样的。它逐个字符解析HTML,并将所有相关部分存储在类似树形的数据结构中。 - BalusC
3个回答

0

我遇到了类似的问题 - 给定一个HTML字符串,我想要将所有的tio2替换为TiO<sub>2</sub>,并将ticl4替换为TiCl<sub>4</sub>

使用简单的字符串替换很容易实现,但有些情况下“needle”字符串出现在域名中,例如www.ilovetio2.comwww.tastytastyticl4.info。在这些情况下,字符串替换会破坏href属性。

与其试图找到一个复杂的正则表达式,不如对HTML字符串进行两次处理:

  • 使用str_ireplace替换所有实例
  • 查找包含<sub>...</sub>的href属性并使用preg_replace_callback修复它们

    public static function subscriptStrings($str)
    {
    
        // $str是任意字符串,可能是HTML,也可能是纯文本
    
        // 定义搜索/替换
        $map = [
            'tio2' => 'TiO<sub>2</sub>',
            'ticl4' => 'TiCl<sub>4</sub>'
        ];
    
        // 替换所有实例,不考虑它们的上下文
        $str = str_ireplace(array_keys($map), array_values($map), $str);
    
        // 进行第二次处理,专门查找href值
        $str = preg_replace_callback('/href="[^"]+"/', function ($str) {
    
            // 返回去除<sub>标签的hrefreturn str_replace(['<sub>', '</sub>'], '', $str[0]);
        }, $str);
    
        return $str;
    }
    

这并不是万无一失的,如果有些链接由于某种原因应该在其中包含,那么它将失败。


0
\b(replace_me)\b(?!(?:(?!<\/?[ha].*?>).)*<\/[ha].*?>)(?![^<>]*>)

0

使用正则表达式解析HTML是一个糟糕的想法,会让你发疯。在这上面使用正则表达式可能不会那么糟糕,但无论采取什么方法,都需要考虑以下几点:

  1. 页面中有多少个这样的内容?
  2. 你将对多少个页面进行此操作?
  3. 输出结果是否需要手动检查,还是自动化处理?
  4. 你将使用哪种编程语言来完成此操作?

我认为最好的方法不是使用“简单”(读作:极其复杂)的正则表达式,而是使用具有一定逻辑的正确程序 - 当然,如果正则表达式是图灵完备的,并且其他人可以提供一个正则表达式来完成你想要的操作,那就另当别论了 :)


  1. 可能有多个解决方案。 2和3. 自动化的。
  2. PHP
其中一个解决方案可能是先用<noreplace>标记替换所有链接和标题,然后执行忽略这些标记内部内容的正则表达式?
- Vladimir
@Alphax,你只是个懦夫。如果你不想使用正则表达式,那没关系,但不要指望别人也不使用它。 - Dika

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接