在 Javascript 中使用 Regex 删除 HTML 注释

IT技术 javascript regex
2021-02-09 02:18:36

我有一些从 Word 生成的难看的 HTML,我想从中删除所有 HTML 注释。

HTML 如下所示:

<!--[if gte mso 9]><xml> <o:OfficeDocumentSettings> <o:RelyOnVML/> <o:AllowPNG/> </o:OfficeDocumentSettings> </xml><![endif]--><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/> <w:TrackFormatting/> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>NO-BOK</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:EnableOpenTypeKerning/> <w:DontFlipMirrorIndents/> <w:OverrideTableStyleHps/> </w:Compatibility> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="&#45;-"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]-->

..我使用的正则表达式就是这个

html = html.replace(/<!--(.*?)-->/gm, "")

但是好像没有匹配,字符串没有变化。

我缺少什么?

6个回答

正则表达式/<!--[\s\S]*?-->/g应该可以工作。

您将杀死CDATA 块中的转义文本跨度

例如

<script><!-- notACommentHere() --></script>

和格式化代码块中的文字文本

<xmp>I'm demoing HTML <!-- comments --></xmp>

<textarea><!-- Not a comment either --></textarea>

编辑:

这也不会阻止引入新的评论,如

<!-<!-- A comment -->- not comment text -->

在一轮正则表达式之后将成为

<!-- not comment text -->

如果这是一个问题,您可以转义<不属于注释或标签的部分(复杂到正确),或者您可以按上述方式循环和替换,直到字符串稳定下来。


这是一个正则表达式,它将根据 HTML-5 规范匹配注释,包括伪注释和未关闭的注释。CDATA 部分只在外部 XML 中被严格允许。这受到与上述相同的警告。

var COMMENT_PSEUDO_COMMENT_OR_LT_BANG = new RegExp(
    '<!--[\\s\\S]*?(?:-->)?'
    + '<!---+>?'  // A comment with no body
    + '|<!(?![dD][oO][cC][tT][yY][pP][eE]|\\[CDATA\\[)[^>]*>?'
    + '|<[?][^>]*>?',  // A pseudo-comment
    'g');
请举例用法?
2021-03-14 02:18:36
@MikeSamuel 您的最后一段代码在 CDATA 周围遗漏了两个反斜杠转义符。
2021-03-28 02:18:36
@guiomie,我不明白你的目标。请详细解释一下?
2021-04-01 02:18:36
这是一个很好的解决方案,谢谢。我正在尝试修改它以捕获分布在多行中的评论。对此有何想法?值得一个新问题吗?
2021-04-02 02:18:36
您将如何修改它以仅获取评论并删除 html ?
2021-04-04 02:18:36

这是基于Aurielle Perlmann 的回答,它支持所有情况(单行、多行、未终止和嵌套注释):

/(<!--.*?-->)|(<!--[\S\s]+?-->)|(<!--[\S\s]*?$)/g

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

regex101 输出

你应该使用/s修饰符

html = html.replace( /<!--.*?-->/sg, "")

在 perl 中测试:

use strict;
use warnings;

my $str = 'hello <!--[if gte mso 9]><xml> <o:OfficeDocumentSettings> <o:RelyOnVML/> <o:AllowPNG/> </o:OfficeDocumentSettings> </xml><![endif]--><!--[if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:TrackMoves/> <w:TrackFormatting/> <w:HyphenationZone>21</w:HyphenationZone> <w:PunctuationKerning/> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:DoNotPromoteQF/> <w:LidThemeOther>NO-BOK</w:LidThemeOther> <w:LidThemeAsian>X-NONE</w:LidThemeAsian> <w:LidThemeComplexScript>X-NONE</w:LidThemeComplexScript> <w:Compatibility> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:SplitPgBreakAndParaMark/> <w:EnableOpenTypeKerning/> <w:DontFlipMirrorIndents/> <w:OverrideTableStyleHps/> </w:Compatibility> <m:mathPr> <m:mathFont m:val="Cambria Math"/> <m:brkBin m:val="before"/> <m:brkBinSub m:val="&#45;-"/> <m:smallFrac m:val="off"/> <m:dispDef/> <m:lMargin m:val="0"/> <m:rMargin m:val="0"/> <m:defJc m:val="centerGroup"/> <m:wrapIndent m:val="1440"/> <m:intLim m:val="subSup"/> <m:naryLim m:val="undOvr"/> </m:mathPr></w:WordDocument> </xml><![endif]-->world!';

$str =~ s/<!--.*?-->//sg;
print $str;

输出:
hello world!

JavaScript 没有s修饰符。使用[\s\S]代替.
2021-03-25 02:18:36

这也适用于多行 - (<!--.*?-->)|(<!--[\w\W\n\s]+?-->)

在此处输入图片说明

我最近需要做这件事(即从 html 文件中删除所有评论)。这些其他答案没有考虑到的一些事情;

  1. 一个 html 文件可以有 css 和 JS 内联,我想至少去掉
  2. 字符串或正则表达式中的注释语法是完全有效的。(我的字符串/正则表达式排除模式基于:https : //stackoverflow.com/a/23667311/3799617

TLDR:(我只想要删除所有评论的正则表达式,plz)

/\\\/|\/\s*(?:\\\/|[^\/\*\n])+\/|\\"|"(?:\\"|[^"])*"|\\'|'(?:\\'|[^'])*'|\\`|`(?:\\`|[^`])*`|(\/\/[\s\S]*?$|(?:<!--|\/\s*\*)\s*[\s\S]*?\s*(?:-->|\*\s*\/))/gm

这是一个简单的演示:https : //www.regexr.com/5fjlu


我不讨厌阅读,剩下的给我看看:

我还需要进行各种其他匹配,这些匹配考虑了包含以其他方式显示为有效目标的内容的有效字符串。所以我做了一个类来处理我的各种用途。

class StringAwareRegExp extends RegExp {
    static get [Symbol.species]() { return RegExp; }

    constructor(regex, flags){
        if(regex instanceof RegExp) regex = StringAwareRegExp.prototype.regExpToInnerRegexString(regex);

        regex = super(`${StringAwareRegExp.prototype.disqualifyStringsRegExp}(${regex})`, flags);

        return regex;
    }

    stringReplace(sourceString, replaceString = ''){
        return sourceString.replace(this, (match, group1) => { return group1 === undefined ? match : replaceString; });
    }
}

StringAwareRegExp.prototype.regExpToInnerRegexString = function(regExp){ return regExp.toString().replace(/^\/|\/[gimsuy]*$/g, ''); };
Object.defineProperty(StringAwareRegExp.prototype, 'disqualifyStringsRegExp', {
    get: function(){
        return StringAwareRegExp.prototype.regExpToInnerRegexString(/\\\/|\/\s*(?:\\\/|[^\/\*\n])+\/|\\"|"(?:\\"|[^"])*"|\\'|'(?:\\'|[^'])*'|\\`|`(?:\\`|[^`])*`|/);
    }
});

由此,我又创建了两个类来磨练我需要的两种主要匹配类型:

class CommentRegExp extends StringAwareRegExp {
    constructor(regex, flags){
        if(regex instanceof RegExp) regex = StringAwareRegExp.prototype.regExpToInnerRegexString(regex);

        return super(`\\/\\/${regex}$|(?:<!--|\\/\\s*\\*)\\s*${regex}\\s*(?:-->|\\*\\s*\\/)`, flags);
    }
}

class StatementRegExp extends StringAwareRegExp {
    constructor(regex, flags){
        if(regex instanceof RegExp) regex = StringAwareRegExp.prototype.regExpToInnerRegexString(regex);

        return super(`${regex}\\s*;?\\s*?`, flags);
    }
}

最后(无论对谁有用)正则表达式由此创建:

const allCommentsRegex = new CommentRegExp(/[\s\S]*?/, 'gm');
const enableBabelRegex = new CommentRegExp(/enable-?_?\s?babel/, 'gmi');
const disableBabelRegex = new CommentRegExp(/disable-?_?\s?babel/, 'gmi');
const includeRegex = new CommentRegExp(/\s*(?:includes?|imports?|requires?)\s+(.+?)/, 'gm');
const importRegex = new StatementRegExp(/import\s+(?:(?:\w+|{(?:\s*\w\s*,?\s*)+})\s+from)?\s*['"`](.+?)['"`]/, 'gm');
const requireRegex = new StatementRegExp(/(?:var|let|const)\s+(?:(?:\w+|{(?:\s*\w\s*,?\s*)+}))\s*=\s*require\s*\(\s*['"`](.+?)['"`]\s*\)/, 'gm');
const atImportRegex = new StatementRegExp(/@import\s*['"`](.+?)['"`]/, 'gm');

最后,如果有人愿意看到它在使用中。这是我在其中使用的项目(..我的个人项目始终是 WIP..):https : //github.com/fatlard1993/page-compiler