RegEx para correspondência / substituição de comentários JavaScript (multilinha e inline)

Preciso remover todos os comentários JavaScript de uma fonte JavaScript usando o object JavaScript RegExp.

O que eu preciso é o padrão para o RegExp.

Até agora, eu encontrei isto:

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

Este padrão funciona bem para:

 /* I'm a comment */ 

ou para:

 /* * I'm a comment aswell */ 

Mas parece que não funciona para o inline:

 // I'm an inline comment 

Eu não sou muito especialista em RegEx e seus padrões, então preciso de ajuda.

Além disso, gostaria de ter um padrão RegEx que remova todos os comentários semelhantes a HTML.

  or  

E também esses comentários HTML condicionais, que podem ser encontrados em várias fonts JavaScript.

Obrigado.

tente isso,

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

Deveria trabalhar 🙂 insira a descrição da imagem aqui

NOTA: o Regex não é um léxico ou um analisador . Se você tiver algum caso de borda estranho em que você precisa de alguns comentários nesteds de forma estranha analisados ​​de uma string, use um analisador. Para os outros 98% do tempo, este regex deve funcionar.

Eu tinha comentários de blocos bem complexos com asteriscos nesteds, barras, etc. A expressão regular no site a seguir funcionava como um encanto:

http://upshots.org/javascript/javascript-regexp-to-remove-comments
(veja abaixo para o original)

Algumas modificações foram feitas, mas a integridade da regex original foi preservada. Para permitir certas sequências de barra dupla ( // ) (como URLs), você deve usar a referência de volta $1 em seu valor de substituição em vez de uma seqüência vazia . Aqui está:

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

CASOS DE UTILIZAÇÃO FALHADORES: Existem alguns casos extremos em que esta regex falha. Uma lista contínua desses casos está documentada nesta essência pública . Por favor, atualize a essência se você puder encontrar outros casos.

… e se você também quiser remover use isto:

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

(original – apenas para referência histórica)

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

Eu tenho colocado togethor uma expressão que precisa fazer algo semelhante.
o produto acabado é:

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

Assustador certo?

Para dividi-lo, a primeira parte corresponde a qualquer um entre aspas simples ou duplas
Isso é necessário para evitar correspondência de strings entre aspas

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

a segunda parte corresponde a comentários multilinhas delimitados por / * * /

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

A terceira parte corresponde a comentários de linha única começando em qualquer lugar da linha

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

A quarta até a sexta partes corresponde a qualquer coisa dentro de um literal de expressão regular
Isso depende de um sinal de igual precedente ou do literal antes ou depois de uma chamada regex

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

e o sétimo que eu esqueci originalmente remove os comentários html

 ().)*-->) 

Eu tive um problema com o meu ambiente dev emite erros para um regex que quebrou uma linha, então usei a seguinte solução

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

Isso retorna qualquer coisa capturada pelo texto de string entre aspas e qualquer coisa encontrada em um literal de regex intacto, mas retorna uma string vazia para todas as capturas de comentários.

Eu sei que isso é excessivo e bastante difícil de manter, mas parece funcionar para mim até agora.

É tarde para ser de muita utilidade para a questão original, mas talvez ajude alguém.

Com base na resposta de @Ryan Wheale, descobri que isso funciona como uma captura abrangente para garantir que as correspondências excluam qualquer coisa encontrada dentro de uma string literal.

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

O último grupo (todos os outros são descartados) é baseado na resposta de Ryan. Exemplo aqui

Isso pressupõe código é bem estruturado e válido javascript.

Observação: isso não foi testado em código mal estruturado, que pode ou não ser recuperável, dependendo da heurística do mecanismo de javascript.

Nota: isso deve ser válido para o javascript


No entanto, ainda é possível corresponder a algo que se parece com um comentário dentro de um literal de expressão regular (veja comentários / resultados no Exemplo acima).

Eu uso a captura acima depois de replace todos os literais de regex usando a seguinte captura abrangente extraída de es5-lexer aqui e aqui , como referenciado na resposta de Mike Samuel a esta pergunta :

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

Para completar, veja também esta advertência trivial .

Isso funciona para quase todos os casos:

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

O código é baseado em regexes do jspreproc, eu escrevi essa ferramenta para o compilador de tumulto .

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

Se você clicar no link abaixo, você encontrará um script de remoção de comentários escrito em regex.

Estas são 112 linhas de código que trabalham em conjunto também funciona com mootools e Joomla e drupal e outros sites de cms. Testado em 800.000 linhas de código e comentários. funciona bem. Este também seleciona vários parênteses como (abc (/ nn / (‘/ xvx /’)) “// linha de teste”) e comentários que estão entre dois pontos e os protegem. 23-01-2016 ..! Este é o código com os comentários nele !!!!

Clique aqui

Em simples regex JS simples, isso:

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

Eu me pergunto se essa foi uma pergunta capciosa dada por um professor aos alunos. Por quê? Porque me parece que é impossível fazer isso, com expressões regulares, no caso geral.

Seu (ou o código de quem quer que seja) pode conter JavaScript válido como este:

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

Agora, se você tiver um regexp que remova tudo entre um par de / * e * /, ele quebraria o código acima, também removeria o código executável no meio.

Se você tentar criar um regexp que não remova comentários que contenham citações, não será possível remover esses comentários. Isso se aplica a aspas simples, aspas duplas e aspas traseiras.

Você não pode remover (todos) os comentários com expressões regulares em JavaScript, parece-me, talvez alguém possa apontar uma maneira como fazê-lo para o caso acima.

O que você pode fazer é criar um pequeno analisador que passe pelo caractere de código por caractere e saiba quando ele está dentro de uma string e quando está dentro de um comentário, e quando está dentro de um comentário dentro de uma string e assim por diante.

Tenho certeza de que existem bons analisadores JavaScript de código aberto que podem fazer isso. Talvez algumas das ferramentas de embalagem e de mineração também possam fazer isso por você.

Para comentário de bloco: https://regex101.com/r/aepSSj/1

Corresponde ao caractere de barra (o \1 ) somente se o caractere de barra for seguido por um asterisco.

(\/)(?=\*)

talvez seguido por outro asterisco

(?:\*)

seguido pelo primeiro grupo de jogo, ou zero ou mais vezes a partir de algo … talvez, sem lembrar a partida, mas capturar como um grupo.

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

seguido de asterisco e primeiro grupo

(?:\*)\1

Para comentários em bloco e / ou inline: https://regex101.com/r/aepSSj/2

onde | significa ou e (?=\/\/(.*)) capturar qualquer coisa depois de qualquer //

ou https://regex101.com/r/aepSSj/3 para capturar a terceira parte também

tudo em: https://regex101.com/r/aepSSj/8

Com base nas tentativas acima e usando UltraEdit, principalmente Abhishek Simon, eu achei isso para trabalhar para comentários in-line e lida com todos os personagens dentro do comentário.

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

Isso corresponde aos comentários no início da linha ou com um espaço antes de //

// public static final String LETTERS_WORK_FOLDER = “/ Cartas / Gerado / Trabalho”;

mas não

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

por isso só não é bom para algo como

if (x) {f (x)} // onde f é alguma function

só precisa ser

if (x) {f (x)} // onde f é function