wake-up-neo.com

RegEx zum Abgleichen/Ersetzen von JavaScript-Kommentaren (sowohl mehrzeilig als auch inline)

Ich muss alle JavaScript-Kommentare aus einem JavaScript-Quellcode mithilfe des JavaScript-RegExp-Objekts entfernen.

Was ich brauche, ist das Muster für die RegExp.

Bisher habe ich das gefunden:

compressed = compressed.replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '');

Dieses Muster funktioniert in Ordnung für:

/* I'm a comment */

oder für:

/*
 * I'm a comment aswell
*/

Scheint aber nicht für die Inline zu funktionieren:

// I'm an inline comment

Ich bin kein Experte für RegEx und seine Muster, also brauche ich Hilfe.

Außerdem möchte ich ein RegEx-Muster haben, das alle HTML-artigen Kommentare entfernt.

<!-- HTML Comment //--> or <!-- HTML Comment -->

Und auch die bedingten HTML-Kommentare, die in verschiedenen JavaScript-Quellen zu finden sind.

Vielen Dank.

33
metaforce

versuche dies,

(\/\*[\w\'\s\r\n\*]*\*\/)|(\/\/[\w\s\']*)|(\<![\-\-\s\w\>\/]*\>)

sollte arbeiten :)enter image description here

17
abi1964

HINWEIS: Regex ist kein Lexer oder Parser . Wenn Sie einen seltsamen Edge-Fall haben, in dem Sie aus einer Zeichenfolge heraus merkwürdig verschachtelte Kommentare benötigen, verwenden Sie einen Parser. In den übrigen 98% der Fälle sollte dieser Regex funktionieren.

Ich hatte ziemlich komplexe Blockkommentare mit verschachtelten Sternchen, Schrägstrichen usw. Der reguläre Ausdruck auf der folgenden Seite funktionierte wie ein Zauber:

http://upshots.org/javascript/javascript-regexp-to-remove-comments
(Original siehe unten)

Es wurden einige Änderungen vorgenommen, die Integrität des ursprünglichen Regex blieb jedoch erhalten. Um bestimmte doppelte Schrägstriche (//) (z. B. URLs) zuzulassen, müssen Sie in Ihrem Ersetzungswert anstelle der leeren Zeichenfolge den Rückverweis $1 verwenden. Hier ist es:

/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm

// JavaScript: 
// source_string.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1');

// PHP:
// preg_replace("/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/m", "$1", $source_string);

DEMO:http://www.regextester.com/?fam=96247

FAILING USE CASES: Es gibt einige Edge-Fälle, in denen diese Regex fehlschlägt. Eine laufende Liste dieser Fälle ist in this public Gist dokumentiert. Bitte aktualisieren Sie die Gist, wenn Sie andere Fälle finden.

... und wenn Sie auch<!-- html comments --> entfernen möchten, verwenden Sie Folgendes:

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

(Original - nur zur historischen Referenz)

/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm
60
Ryan Wheale

Ich habe einen Ausdruck gefunden, der etwas Ähnliches tun muss.
Das fertige Produkt ist: 

/(?:((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)|(\/\*(?:(?!\*\/).|[\n\r])*\*\/)|(\/\/[^\n\r]*(?:[\n\r]+|$))|((?:=|:)\s*(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))|((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)[gimy]?\.(?:exec|test|match|search|replace|split)\()|(\.(?:exec|test|match|search|replace|split)\((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))|(<!--(?:(?!-->).)*-->))/g

Unheimlich richtig?

Um es aufzuschlüsseln, stimmt der erste Teil mit beliebigen Anführungszeichen überein
Dies ist erforderlich, um das Anpassen von Zeichenfolgen in Anführungszeichen zu vermeiden

((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)

der zweite Teil enthält mehrzeilige Kommentare, die durch/* */getrennt sind.

(\/\*(?:(?!\*\/).|[\n\r])*\*\/)

Der dritte Teil enthält einzeilige Kommentare, die an einer beliebigen Stelle in der Zeile beginnen

(\/\/[^\n\r]*(?:[\n\r]+|$))

Der vierte bis sechste Teil stimmt mit allem innerhalb eines Regex-Literal überein
Dies setzt ein vorangestelltes Gleichheitszeichen oder das Literal vor oder nach einem Regex-Aufruf voraus

((?:=|:)\s*(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))
((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)[gimy]?\.(?:exec|test|match|search|replace|split)\()
(\.(?:exec|test|match|search|replace|split)\((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))

und die siebte, die ich ursprünglich vergessen habe, entfernt die HTML-Kommentare

(<!--(?:(?!-->).)*-->)

Ich hatte ein Problem mit meiner Dev-Umgebung, die Fehler für einen regulären Ausdruck ausbrach, der eine Zeile durchbrach. Daher habe ich die folgende Lösung verwendet

var ADW_GLOBALS = new Object
ADW_GLOBALS = {
  quotations : /((["'])(?:(?:\\\\)|\\\2|(?!\\\2)\\|(?!\2).|[\n\r])*\2)/,
  multiline_comment : /(\/\*(?:(?!\*\/).|[\n\r])*\*\/)/,
  single_line_comment : /(\/\/[^\n\r]*[\n\r]+)/,
  regex_literal : /(?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/)/,
  html_comments : /(<!--(?:(?!-->).)*-->)/,
  regex_of_Doom : ''
}
ADW_GLOBALS.regex_of_Doom = new RegExp(
  '(?:' + ADW_GLOBALS.quotations.source + '|' + 
  ADW_GLOBALS.multiline_comment.source + '|' + 
  ADW_GLOBALS.single_line_comment.source + '|' + 
  '((?:=|:)\\s*' + ADW_GLOBALS.regex_literal.source + ')|(' + 
  ADW_GLOBALS.regex_literal.source + '[gimy]?\\.(?:exec|test|match|search|replace|split)\\(' + ')|(' + 
  '\\.(?:exec|test|match|search|replace|split)\\(' + ADW_GLOBALS.regex_literal.source + ')|' +
  ADW_GLOBALS.html_comments.source + ')' , 'g'
);

changed_text = code_to_test.replace(ADW_GLOBALS.regex_of_Doom, function(match, $1, $2, $3, $4, $5, $6, $7, $8, offset, original){
  if (typeof $1 != 'undefined') return $1;
  if (typeof $5 != 'undefined') return $5;
  if (typeof $6 != 'undefined') return $6;
  if (typeof $7 != 'undefined') return $7;
  return '';
}

Dies gibt alles zurück, was durch den in Anführungsstrichen genannten String-Text und alles, was in einem Regex-Literal gefunden wurde, intakt ist, gibt jedoch einen leeren String für alle Kommentarerfassungen zurück.

Ich weiß, das ist übertrieben und ziemlich schwer aufrechtzuerhalten, aber es scheint mir bisher zu funktionieren.

6
wolffer-east

In einfachen einfachen JS Regex:

my_string_or_obj.replace(/\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm, ' ')
2
Shobhit Sharma

Dies ist zu spät, um der ursprünglichen Frage von Nutzen zu sein, aber vielleicht hilft sie jemandem.

Basierend auf der Antwort von @Ryan Wheale habe ich festgestellt, dass dies als umfassende Erfassung funktioniert, um sicherzustellen, dass Übereinstimmungen alles ausschließen, was in einem String-Literal gefunden wird.

/(?:\r\n|\n|^)(?:[^'"])*?(?:'(?:[^\r\n\\']|\\'|[\\]{2})*'|"(?:[^\r\n\\"]|\\"|[\\]{2})*")*?(?:[^'"])*?(\/\*(?:[\s\S]*?)\*\/|\/\/.*)/g

Die letzte Gruppe (alle anderen werden verworfen) basiert auf Ryans Antwort. Beispiel hier .

Dies setzt voraus, dass der Code gut strukturiert ist und gültiges Javascript verwendet.

Hinweis: Dies wurde nicht mit schlecht strukturiertem Code getestet, der abhängig von den eigenen Heuristiken der Javascript-Engine möglicherweise wiederhergestellt werden kann.

Hinweis: Dies sollte für gültiges Javascript <ES6 gelten, jedoch erlaubt ES6 mehrzeilige String-Literale . In diesem Fall wird dieser Regex fast sicher brechen, obwohl dieser Fall nicht getestet wurde.


Es ist jedoch immer noch möglich, etwas zu finden, das wie ein Kommentar in einem Regex-Literal aussieht (siehe Kommentare/Ergebnisse im obigen Beispiel).

Ich benutze das obige Capture, nachdem ich alle Regex-Literale durch das folgende umfassende Capture ersetzt habe, das aus es5-lexer hier und hier extrahiert wurde, wie in Mike Samuel s Antwort auf diese Frage :

/(?:(?:break|case|continue|delete|do|else|finally|in|instanceof|return|throw|try|typeof|void|[+]|-|[.]|[/]|,|[*])|[!%&(:;<=>?[^{|}~])?(\/(?![*/])(?:[^\\\[/\r\n\u2028\u2029]|\[(?:[^\]\\\r\n\u2028\u2029]|\\(?:[^\r\n\u2028\u2029ux]|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}))+\]|\\(?:[^\r\n\u2028\u2029ux]|u[0-9A-Fa-f]{4}|x[0-9A-Fa-f]{2}))*\/[gim]*)/g

Zur Vollständigkeit siehe auch diesen unbedeutenden Vorbehalt .

2
Nolo

Das funktioniert in fast allen Fällen:

var RE_BLOCKS = new RegExp([
  /\/(\*)[^*]*\*+(?:[^*\/][^*]*\*+)*\//.source,           // $1: multi-line comment
  /\/(\/)[^\n]*$/.source,                                 // $2 single-line comment
  /"(?:[^"\\]*|\\[\S\s])*"|'(?:[^'\\]*|\\[\S\s])*'/.source, // - string, don't care about embedded eols
  /(?:[$\w\)\]]|\+\+|--)\s*\/(?![*\/])/.source,           // - division operator
  /\/(?=[^*\/])[^[/\\]*(?:(?:\[(?:\\.|[^\]\\]*)*\]|\\.)[^[/\\]*)*?\/[gim]*/.source
  ].join('|'),                                            // - regex
  'gm'  // note: global+multiline with replace() need test
);

// remove comments, keep other blocks
function stripComments(str) {
  return str.replace(RE_BLOCKS, function (match, mlc, slc) {
    return mlc ? ' ' :         // multiline comment (replace with space)
           slc ? '' :          // single/multiline comment
           match;              // divisor, regex, or string, return as-is
  });
}

Der Code basiert auf Regex von jspreproc. Ich habe dieses Tool für den riot-Compiler geschrieben.

Siehe http://github.com/aMarCruz/jspreproc

2
aMarCruz

etwas einfacher - 

das funktioniert auch für mehrzeilig - (<!--.*?-->)|(<!--[\w\W\n\s]+?-->)

 enter image description here

1

Wenn Sie auf den Link unten klicken, finden Sie ein Skript zum Entfernen von Kommentaren, das in Regex geschrieben ist. 

Dies sind 112 Zeilen Off-Code, der zusammen mit Mootools und Joomla und Drupal und anderen cms-Websites funktioniert. Getestet mit 800.000 Codezeilen und Kommentaren. funktioniert gut. Dieser wählt auch mehrere Klammern wie (abc (/ nn/('/ xvx /') "// Testzeile") und Kommentare aus, die zwischen Doppelpunkten stehen und diese schützen 23-01-2016 ..! Dies ist der Code mit den Kommentaren. !!!! 

Klick hier

1
John Smith

Ich suchte auch nach einer schnellen Regex-Lösung, aber keine der Antworten lieferte 100%. Jeder bricht den Quellcode auf irgendeine Weise, hauptsächlich aufgrund von Kommentaren, die in String-Literalen gefunden wurden. Z.B.

var string = "https://www.google.com/";

Wird

var string = "https:

Zum Nutzen derjenigen, die von Google kommen, schrieb ich schließlich eine kurze Funktion (in Javascript), mit der erreicht wird, was die Regex nicht konnte. Ändern Sie die Sprache für die Sprache, die Sie zum Parsen von Javascript verwenden.

function removeCodeComments(code) {
    var inQuoteChar = null;
    var inBlockComment = false;
    var inLineComment = false;
    var inRegexLiteral = false;
    var newCode = '';
    for (var i=0; i<code.length; i++) {
        if (!inQuoteChar && !inBlockComment && !inLineComment && !inRegexLiteral) {
            if (code[i] === '"' || code[i] === "'" || code[i] === '`') {
                inQuoteChar = code[i];
            }
            else if (code[i] === '/' && code[i+1] === '*') {
                inBlockComment = true;
            }
            else if (code[i] === '/' && code[i+1] === '/') {
                inLineComment = true;
            }
            else if (code[i] === '/' && code[i+1] !== '/') {
                inRegexLiteral = true;
            }
        }
        else {
            if (inQuoteChar && ((code[i] === inQuoteChar && code[i-1] != '\\') || (code[i] === '\n' && inQuoteChar !== '`'))) {
                inQuoteChar = null;
            }
            if (inRegexLiteral && ((code[i] === '/' && code[i-1] !== '\\') || code[i] === '\n')) {
                inRegexLiteral = false;
            }
            if (inBlockComment && code[i-1] === '/' && code[i-2] === '*') {
                inBlockComment = false;
            }
            if (inLineComment && code[i] === '\n') {
                inLineComment = false;
            }
        }
        if (!inBlockComment && !inLineComment) {
            newCode += code[i];
        }
    }
    return newCode;
}

0
user2867288

2019:

Die ganze Antwort hier war nicht so gut. damit ich etwas besseres schreibe, probiere es aus:

function striptComment(code){
 return code
 // remove multi line comment /* */
 .replace(/(\t*\/\*[\s\S]*?\*(\n?)\/)/gm, '')
 // remove one line comment //
 // there is some hack here, to skip "'//'" or http://..' 
 .replace(/([\t ]+(?!"'.*)\/\/[\s\S]*?(?=\n))/gm, '')
 // remove html comment <!-- --> 
 .replace(/(\t*<!--[\s\S]*?-->\n?)/gm, '')
 // bonus:
 // encode " and ' in the string (' -> \' ..)
 .replace(/(['"])/gm,"\\$1")
 // clean new line and tabs */
 .replace(/[\n\t\r]+/gm,"")
 ;
}
// example
striptComment(striptComment.toString())
// function striptComment(code){ return code .replace(/(\t*\/\*[\s\S]*?\*(\n?)\/)/gm, \'\') .replace(/([\t ]+(?!\"\'.*)\/\/[\s\S]*?(?=\n))/gm, \'\') .replace(/(\t*\n?)/gm, \'\') .replace(/([\'\"])/gm,\"\\$1\") .replace(/[\n\t\r]+/gm,\"\") ;}

0
pery mimon

Ich frage mich, ob dies eine Trickfrage war, die ein Professor an Studenten gerichtet hatte. Warum? Weil es mir scheint, ist es UNM&OUML;GLICH, dies zu tun, mit Regulären Ausdrücken im Allgemeinen. 

Ihr (oder wer auch immer der Code ist) kann Gültiges JavaScript wie folgt enthalten:

let a = "hello /* ";
let b = 123;
let c = "world */ ";

Wenn Sie nun einen Regex haben, der alles. Zwischen einem Paar von/* und */entfernt, würde der obige Code .__ gebrochen, der ausführbare Code in der Mitte von

Wenn Sie versuchen, einen regulären Ausdruck zu entwickeln, werden Kommentare, die Anführungszeichen enthalten, nicht entfernt. Dann können Sie solche Kommentare nicht entfernen. Dies gilt für einfache Anführungszeichen, Anführungszeichen und Anführungszeichen.

Sie können (alle) Kommentare nicht mit regulären Ausdrücken in JavaScript entfernen, es scheint mir, Vielleicht kann jemand einen Weg aufzeigen, wie er dies tun soll. 

Sie können einen kleinen Parser erstellen, der Den Code zeichenweise durchläuft Und weiß, wann er sich in einem String befindet und wannit in einem Kommentar enthalten ist und wann er sich in Befindet. ein Kommentar innerhalb einer Zeichenfolge und so weiter. 

Ich bin sicher, es gibt gute Open Source-JavaScript-Parser, die dies tun können. Möglicherweise können einige der Paketierungs- und Minimierungswerkzeuge dies auch für Sie tun.

0
Panu Logic

Für Blockkommentar: https://regex101.com/r/aepSSj/1

Stimmt nur mit einem Schrägstrich (dem \1) überein, wenn auf den Schrägstrich ein Sternchen folgt.

(\/)(?=\*)

vielleicht gefolgt von einem weiteren Sternchen

(?:\*)

gefolgt von der ersten Matchgruppe oder null oder mehrmals von etwas ... vielleicht, ohne sich an das Match zu erinnern, aber als Gruppe festhalten.

((?:\1|[\s\S])*?)

gefolgt von einem Sternchen und der ersten Gruppe

(?:\*)\1

Für Block- und/oder Inline-Kommentar: https://regex101.com/r/aepSSj/2

wobei | bedeutet oder und (?=\/\/(.*)) etwas nach einem // erfassen

oder https://regex101.com/r/aepSSj/3 , um auch den dritten Teil zu erfassen

all in: https://regex101.com/r/aepSSj/8

0
Adrian Miranda