代码之家  ›  专栏  ›  技术社区  ›  Strider

使用正则表达式替换内部HTML文本时的性能问题

  •  0
  • Strider  · 技术社区  · 5 年前

    当调用使用正则表达式替换innerHTML文本的方法时,我面临性能问题:

    function getReplacedText(textToReplace) {
      return textToReplace.replace(/\<img src=[\"|\']([\S\s]+\\)*([\S\s]+).png[\"|\']\/\>/i,"*$2*");
    }
    

    这次替换的目的是 innerHTML 一个 contentEditable div 在keyup处理程序函数中,并替换每个 img 用文件名标记。在我的例子中,为了知道被替换的文本是否超过了可编辑div允许的最大长度,这个替换是必要的。

    function keyupHandler(event) {
      var myEditableDiv = document.getElementById("editableDiv");
      const currentText = getReplacedText(myEditableDiv.innerHTML);
      if (currentText.length >= 750) { //750 is the max length
        event.preventDefault();
      }
    }
    

    例如,所需的输出 abc <img src="assets\test\1F619.png"> def 会是 abc *1F619* def

    当我不使用 getReplacedText 我没有任何性能问题。你能告诉我一个更好的方法或者更好地使用正则表达式吗?

    这是性能开始下降时要替换的文本示例:

    dsd<img src="assets\test\1F619.png"/><img src="assets\test\1F619.png"/><img src="assets\test\1F629.png"/><img src="assets\test\1F630.png"/>sdfsdfsdffsdf<img src="assets\test\1F629.png"/>sdfsdsdfsdf<img src="assets\test\1F627.png"/><img src="assets\test\1F631.png"/>sdfsdfsdf<img src="assets\test\1F631.png"/>sdfsdfsdf<img src="assets\test\1F632.png"/>sdfsdfs<img src="assets\test\1F629.png"/><img src="assets\test\1F629.png"/>sdfs<img src="assets\test\1F631.png"/>df<img src="assets\test\1F632.png"/>sdfsdfsdf
    
    3 回复  |  直到 5 年前
        1
  •  2
  •   CertainPerformance    5 年前

    避免使用正则表达式解析HTML。使用 DOMParser 相反-找到 <img> 标记,并将其替换为只包含src的最后部分的文本节点:

    const input = String.raw`dsd<img src="assets\test\1F619.png"><img src="assets\test\1F619.png"><img src="assets\test\1F629.png"><img src="assets\test\1F630.png">sdfsdfsdffsdf<img src="assets\test\1F629.png">sdfsdsdfsdf<img src="assets\test\1F627.png"><img src="assets\test\1F631.png">sdfsdfsdf<img src="assets\test\1F631.png">sdfsdfsdf<img src="assets\test\1F632.png">sdfsdfs<img src="assets\test\1F629.png"><img src="assets\test\1F629.png">sdfs<img src="assets\test\1F631.png">df<img src="assets\test\1F632.png">sdfsdfsdf`;
    const doc = new DOMParser().parseFromString(input, 'text/html');
    doc.querySelectorAll('img[src]').forEach((img) => {
      img.replaceWith(' ' + img.src.match(/[^\/]+(?=\.png$)/)[0] + ' ');
    });
    console.log(doc.body.innerHTML);
        2
  •  2
  •   user557597user557597    5 年前

    你不需要一个dom来解析html标记!!!

    这是最快的方法,而且不会被格式错误的html阻塞。

    查找

    /<img(?=\s)(?=(?:[^>"']|"[^"]*"|'[^']*')*?\ssrc\s*=\s*(?:(['"])(?:(?!\1)[\S\s])*?((?:(?!\1|\\)[\S\s])*?)\.png\s*\1))\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]?)+>/

    替换 *$2*

    https://regex101.com/r/bCYXV1/1

    解释

                            # Begin 'img' tag
     < img
     (?= \s )
     (?=                    # Asserttion (a pseudo atomic group)
          (?: [^>"'] | " [^"]* " | ' [^']* ' )*?
          \s src \s* = \s*       # src attribute
          (?:
               ( ['"] )               # (1), Quote
    
               (?:
                    (?! \1 )
                    [\S\s] 
               )*?
               (                      # (2 start)
                    (?:
                         (?! \1 | \\ )
                         [\S\s] 
                    )*?
               )                      # (2 end)
               \.png                  # find the 'png' file
               \s* 
               \1          
          )
     )
                            # Have the png file, just match the rest of tag
     \s+ 
     (?: " [\S\s]*? " | ' [\S\s]*? ' | [^>]? )+
    
     >                      # End img tag
    

    var input = "dsd<img src=\"assets\\test\\1F619.png\"><img src=\"assets\\test\\1F619.png\"><img src=\"assets\\test\\1F629.png\"><img src=\"assets\\test\\1F630.png\">sdfsdfsdffsdf<img src=\"assets\\test\\1F629.png\">sdfsdsdfsdf<img src=\"assets\\test\\1F627.png\"><img src=\"assets\\test\\1F631.png\">sdfsdfsdf<img src=\"assets\\test\\1F631.png\">sdfsdfsdf<img src=\"assets\\test\\1F632.png\">sdfsdfs<img src=\"assets\\test\\1F629.png\"><img src=\"assets\\test\\1F629.png\">sdfs<img src=\"assets\\test\\1F631.png\">df<img src=\"assets\\test\\1F632.png\">sdfsdfsdf";
    console.log(input.replace(/<img(?=\s)(?=(?:[^>"']|"[^"]*"|'[^']*')*?\ssrc\s*=\s*(?:(['"])(?:(?!\1)[\S\s])*?((?:(?!\1|\\)[\S\s])*?)\.png\s*\1))\s+(?:"[\S\s]*?"|'[\S\s]*?'|[^>]?)+>/g 
    ,"\n*$2*"));
        3
  •  0
  •   Emma    5 年前

    我猜也许这个简单的表达 s 模式可能只是在这里完成工作:

     <img src=["']\s*(\S+.png)\s*["']\s*>
    

    或者如果我们不拍摄图像,

    <img src=["']\s*\S+.png\s*["']\s*>
    

    就够了。

    DEMO