RegEx per la corrispondenza / sostituzione dei commenti JavaScript (sia multilinea che in linea)

Devo rimuovere tutti i commenti JavaScript da un’origine JavaScript utilizzando l’object RegExp JavaScript.

Quello di cui ho bisogno è il pattern per RegExp.

Finora, ho trovato questo:

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

Questo modello funziona OK per:

 /* I'm a comment */ 

o per:

 /* * I'm a comment aswell */ 

Ma non sembra funzionare per la linea:

 // I'm an inline comment 

Non sono un esperto per RegEx e sono modelli, quindi ho bisogno di aiuto.

Inoltre, mi piacerebbe avere un pattern RegEx che rimuova tutti quei commenti in stile HTML.

  or  

E anche i commenti HTML condizionali, che possono essere trovati in varie fonti JavaScript.

Grazie.

prova questo,

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

dovrebbe funzionare 🙂 inserisci la descrizione dell'immagine qui

NOTA: Regex non è un lexer o un parser . Se hai qualche strano caso limite in cui hai bisogno di alcuni commenti stranamente nidificati analizzati da una stringa, usa un parser. Per il restante 98% delle volte questa regex dovrebbe funzionare.

Ho avuto commenti di blocco piuttosto complessi in corso con asterischi, barre, ecc. Nidificati. L’espressione regolare nel seguente sito ha funzionato come un incantesimo:

http://upshots.org/javascript/javascript-regexp-to-remove-comments
(vedi sotto per l’originale)

Alcune modifiche sono state apportate, ma l’integrità della regex originale è stata preservata. Per consentire alcune sequenze di doppia barra ( // ) (come gli URL), è necessario utilizzare il riferimento posteriore $1 nel valore di sostituzione anziché una stringa vuota . Ecco qui:

 /\/\*[\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

CASI DI FALLIMENTO: Ci sono alcuni casi limite in cui questa regex fallisce. Un elenco in corso di questi casi è documentato in questo elenco pubblico . Si prega di aggiornare l’essenza se è ansible trovare altri casi.

… e se vuoi anche rimuovere usa questo:

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

(originale – solo per riferimento storico)

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

Ho fatto di togethor un’espressione che ha bisogno di fare qualcosa di simile.
il prodotto finito è:

 /(?:((["'])(?:(?:\\\\)|\\\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 

Spaventoso giusto?

Per scomporlo, la prima parte corrisponde a qualsiasi virgoletta singola o doppia
Questo è necessario per evitare l’abbinamento di stringhe tra virgolette

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

la seconda parte corrisponde a commenti multilinea delimitati da / * * /

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

La terza parte corrisponde ai commenti a riga singola che iniziano in qualsiasi punto della linea

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

La quarta alla sesta parte corrisponde a qualsiasi cosa all’interno di una regex letterale
Questo si basa su un segno uguale precedente o sull’essere letterale prima o dopo una chiamata regex

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

e il settimo che inizialmente avevo dimenticato rimuove i commenti html

 ().)*-->) 

Ho avuto un problema con il mio ambiente di sviluppo che emetteva errori per una regex che ha rotto una linea, quindi ho usato la seguente soluzione

 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 ''; } 

Ciò restituisce qualsiasi cosa catturata dal testo di stringa quotato e qualsiasi cosa trovata in una regex letterale intatta ma restituisce una stringa vuota per tutte le acquisizioni di commenti.

So che questo è eccessivo e piuttosto difficile da mantenere, ma sembra funzionare per me finora.

Questo è tardi per essere di grande aiuto alla domanda originale, ma forse aiuterà qualcuno.

Basato sulla risposta di @Ryan Wheale, ho trovato che funziona come un’acquisizione completa per garantire che le corrispondenze escludano qualsiasi cosa trovata all’interno di una stringa letterale.

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

L’ultimo gruppo (tutti gli altri sono scartati) si basa sulla risposta di Ryan. Esempio qui .

Questo presuppone che il codice sia ben strutturato e valido javascript.

Nota: questo non è stato testato su un codice mal strutturato che potrebbe non essere recuperabile a seconda dell’euristica del motore javascript.

Nota: questo dovrebbe essere valido per javascript


Tuttavia, è ancora ansible abbinare qualcosa che assomiglia ad un commento all’interno di un regex letterale (vedi commenti / risultati nell’esempio sopra).

Uso la suddetta cattura dopo aver sostituito tutti i regex letterali usando la seguente acquisizione completa estratta da es5-lexer qui e qui , come indicato nella risposta di Mike Samuel a questa domanda :

 /(?:(?: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 

Per completezza, vedi anche questo banale avvertimento .

Questo funziona per quasi tutti i casi:

 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 }); } 

Il codice è basato su regex da jspreproc, ho scritto questo strumento per il compilatore di Riot .

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

Se fai clic sul link in basso, trovi uno script per la rimozione dei commenti scritto in regex.

Questi sono 112 linee fuori codice che funzionano insieme funziona anche con mootools e Joomla e drupal e altri siti Web cms. Testato su 800.000 righe di codice e commenti. funziona bene. Questo seleziona anche più parentesi come (abc (/ nn / (‘/ xvx /’)) “// test line”) e commenti che si trovano tra due punti e li proteggono. 23-01-2016 ..! Questo è il codice con i commenti in esso. !!!!

Clicca qui

In semplice regex JS, questo:

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

Mi chiedo se questa fosse una domanda trabocchetto fatta da un professore agli studenti. Perché? Perché mi sembra IMPOSSIBILE fare questo, con le espressioni regolari, nel caso generale.

Il tuo (o il codice di chiunque sia) può contenere JavaScript valido come questo:

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

Ora, se si ha una espressione regolare che rimuove tutto tra una coppia di / * e * /, interromperà il codice sopra, rimuoverà anche il codice eseguibile nel mezzo.

Se provi a escogitare un’espressione regolare che non rimuova i commenti che contengono virgolette, non puoi rimuovere tali commenti. Questo vale per virgolette singole, virgolette doppie e virgolette posteriori.

Non è ansible rimuovere (tutti) i commenti con le espressioni regolari in JavaScript, mi sembra, forse qualcuno può indicare un modo come farlo per il caso di cui sopra.

Quello che puoi fare è build un parser piccolo che attraversi il codice carattere per carattere e sappia quando si trova all’interno di una stringa e quando si trova all’interno di un commento, e quando si trova all’interno di un commento all’interno di una stringa e così via.

Sono sicuro che ci sono buoni parser JavaScript open source che possono farlo. Forse alcuni degli strumenti di impacchettamento e minifaczione possono farlo anche per te.

Per il commento del blocco: https://regex101.com/r/aepSSj/1

Corrisponde al carattere barra (il \1 ) solo se il carattere barra è seguito da un asterisco.

(\/)(?=\*)

forse seguito da un altro asterisco

(?:\*)

seguito dal primo gruppo di match, o zero o più volte da qualcosa … forse, senza ricordare la partita ma catturare come gruppo.

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

seguito da asterisco e primo gruppo

(?:\*)\1

Per blocco e / o commento in linea: https://regex101.com/r/aepSSj/2

dove | significa o e (?=\/\/(.*)) cattura qualsiasi cosa dopo qualsiasi //

oppure https://regex101.com/r/aepSSj/3 per acquisire anche la terza parte

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

Sulla base dei suddetti tentativi e usando UltraEdit, principalmente Abhishek Simon, ho trovato che questo funzionasse per i commenti in linea e gestiva tutti i personaggi all’interno del commento.

 (\s\/\/|$\/\/)[\w\s\W\S.]* 

Questo corrisponde ai commenti all’inizio della riga o con uno spazio prima //

// public static final String LETTERS_WORK_FOLDER = “/ Letters / Generated / Work”;

ma no

“http://schemas.us.com.au/hub/ ‘>” +

quindi non è buono solo per qualcosa di simile

if (x) {f (x)} // dove f è una funzione

deve solo essere

if (x) {f (x)} // dove f è funzione