V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
kaiki
V2EX  ›  问与答

求一个正则,替换 keyword 且忽略在 html 标签中的内容

  •  
  •   kaiki · 2022-03-30 22:00:41 +08:00 · 1148 次点击
    这是一个创建于 1003 天前的主题,其中的信息可能已经有所发展或是发生改变。
    文本 = 123123<span class="type2">123123</span>123<a href="/123" title="123">123123</a>123
    结果 = 1[2]31[2]3<span class="type2">1[2]3123</span>1[2]3<a href="/123" title="123">1[2]3123</a>1[2]3
    即在 html 标签中的不可以被替换,非 html 标签的则替换为\[\\1]即可,PHP 的 preg_replace ,不过正则应该通用的
    8 条回复    2022-03-31 23:23:06 +08:00
    moen
        1
    moen  
       2022-03-30 22:34:19 +08:00   ❤️ 1
    应当明白一个常识——正则表达式不是万能的,它不能匹配 HTML

    这个需求最简单的方式是找个 HTML 解析工具得到 DOM 然后直接修改其每个 innerText
    kaiki
        2
    kaiki  
    OP
       2022-03-30 22:46:22 +08:00
    @moen 我的确应该把整个文本拆分,然后根据情况替换,我试试吧。
    oneisall8955
        3
    oneisall8955  
       2022-03-31 06:26:49 +08:00 via Android
    解析 dom ,看看有没有类似 jquery contains ?
    BreadKiller
        4
    BreadKiller  
       2022-03-31 09:54:36 +08:00
    以你的需求还是建议你解析 DOM 操作比较好
    kaiki
        5
    kaiki  
    OP
       2022-03-31 11:20:32 +08:00
    @BreadKiller 其实实际使用场景应该只需要过滤 class 、href 、title 即可,感觉只针对这三个来做就行,但是它们得在 html 标签中才需要过滤掉。
    我基本没写过正则写出来的都不行
    Pipecraft
        6
    Pipecraft  
       2022-03-31 16:39:13 +08:00
    @kaiki #5 非 html 标签的内容,把什么替换为什么?"2" 替换为 "[2]"? 例子好像不太对。
    下面是 JS 的正则,PHP 也可用。

    ```
    /((<[^>]+>)*[^<>]*?)(关键字)/gim
    替换为
    $1[$3]
    ```

    kaiki
        7
    kaiki  
    OP
       2022-03-31 18:00:12 +08:00
    @Pipecraft 试了一下没有成功,可能 PHP 里存在一些问题吧,并且 php 的 preg_replace 没有 g 。
    我用 php 自己写了一个
    ```
    function keyword($dat,$keyword){
    $len = strlen($dat);
    $st = -1; //开始
    $ishtml = false;
    $html = '';
    for($i = 0;$i < $len;$i++){
    $s = substr($dat,$i,1);//当前字符
    if(ord($s) == 60){ //<
    if(!$ishtml && $i > 0 && $st + 1 < $i){//在遇到 html 标签开始符号时,进行一次截断,并处理 keyword
    $html .= self::keyword_replace(substr($dat,$st + 1,$i - $st - 1),$keyword);
    }
    $st = $i;
    $ishtml = true;
    }
    if(ord($s) == 62){ //>
    if($st != -1){//在遇到 html 标签结束符号时,进行一次截断
    $html .= substr($dat,$st,$i - $st + 1);
    $ishtml = false;
    $st = $i;
    }
    }
    if(!$ishtml && $i +1 == $len){//在文本的最后一个字符时,进行一次截断,并处理 keyword
    $html .= self::keyword_replace(substr($dat,$st + 1,$i - $st),$keyword);
    }
    }
    return $html;
    }
    ```
    Pipecraft
        8
    Pipecraft  
       2022-03-31 23:23:06 +08:00
    @kaiki #7 PHP 也可以,去掉 g 参数即可。
    ```
    preg_replace("/((<[^>]+>)*[^<>]*?)(关键字)/im", "$1[$3]", $str);
    ```

    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1461 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 17:12 · PVG 01:12 · LAX 09:12 · JFK 12:12
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.