Ответ 1
попробуйте это,
(\/\*[\w\'\s\r\n\*]*\*\/)|(\/\/[\w\s\']*)|(\<![\-\-\s\w\>\/]*\>)
должен работать:)
Мне нужно удалить все комментарии JavaScript из источника JavaScript, используя объект JavaScript RegExp.
Мне нужен шаблон для RegExp.
До сих пор я нашел это:
compressed = compressed.replace(/\/\*.+?\*\/|\/\/.*(?=[\n\r])/g, '');
Этот шаблон работает нормально для:
/* I'm a comment */
или для:
/*
* I'm a comment aswell
*/
Но, похоже, не работает для inline:
// I'm an inline comment
Я не являюсь экспертом для RegEx и его шаблонов, поэтому мне нужна помощь.
Кроме того, я хотел бы иметь шаблон RegEx, который удалит все эти HTML-подобные комментарии.
<!-- HTML Comment //--> or <!-- HTML Comment -->
А также те условные комментарии HTML, которые можно найти в разных источниках JavaScript.
Спасибо.
попробуйте это,
(\/\*[\w\'\s\r\n\*]*\*\/)|(\/\/[\w\s\']*)|(\<![\-\-\s\w\>\/]*\>)
должен работать:)
ПРИМЕЧАНИЕ. Regex не является лексером или парсером. Если у вас есть какой-то странный крайний случай, когда вам нужно разобрать некоторые странно вложенные комментарии из строки, используйте парсер. В остальных 98% случаев это регулярное выражение должно работать.
У меня были довольно сложные блочные комментарии с вложенными звездочками, косыми чертами и т.д. Регулярное выражение на следующем сайте работало как шарм:
http://upshots.org/javascript/javascript-regexp-to-remove-comments
(см. оригинал ниже)
Некоторые изменения были сделаны, но целостность исходного регулярного выражения была сохранена. Чтобы разрешить определенные последовательности с двойной косой чертой (//
) (например, URL-адреса), вы должны использовать обратную ссылку $1
в качестве значения замены вместо пустой строки. Вот оно:
/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm
// JavaScript:
// source_string.replace(/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/gm, '$1');
// PHP:
// preg_replace("/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*$/m", "$1", $source_string);
DEMO: https://regex101.com/r/B8WkuX/1
НЕИСПРАВНОСТЬ ИСПОЛЬЗОВАНИЯ: Есть несколько крайних случаев, когда это регулярное выражение не выполняется. Текущий список этих случаев задокументирован в этой публичной сути. Пожалуйста, обновите суть, если вы можете найти другие случаи.
... и если вы также хотите удалить <!-- html comments -->
, используйте это:
/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*|<!--[\s\S]*?-->$/
(оригинал - только для ознакомления)
// DO NOT USE THIS - SEE ABOVE
/(\/\*([\s\S]*?)\*\/)|(\/\/(.*)$)/gm
Я поставил togethor выражение, которое должно сделать что-то подобное.
готовый продукт:
/(?:((["'])(?:(?:\\\\)|\\\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
Страшно право?
Чтобы разбить его, первая часть соответствует чему-либо внутри одной или двух кавычек
Это необходимо, чтобы избежать сопоставления строк с кавычками
((["'])(?:(?:\\\\)|\\\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)\((?:\/(?:(?:(?!\\*\/).)|\\\\|\\\/|[^\\]\[(?:\\\\|\\\]|[^]])+\])+\/))
и седьмой, который я изначально забыл, удаляет html-комментарии
(<!--(?:(?!-->).)*-->)
У меня возникла проблема с ошибкой, создаваемой средой dev, для регулярного выражения, которое сломало строку, поэтому я использовал следующее решение
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 '';
}
Это возвращает все, что было записано в тексте цитируемой строки, и все, что содержится в литеральном выражении регулярного выражения, но возвращает пустую строку для всех комментариев.
Я знаю, что это чрезмерно и довольно сложно поддерживать, но, похоже, он работает для меня до сих пор.
Это работает практически во всех случаях:
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
});
}
Код основан на регулярных выражениях из jspreproc, я написал этот инструмент для компилятора riot.
Это уже давно очень полезно для первоначального вопроса, но, возможно, это поможет кому-то.
Основываясь на ответе @Ryan Wheale, я нашел, что это работает как всеобъемлющий захват, чтобы гарантировать, что совпадения исключают все, что содержится внутри строкового литерала.
/(?:\r\n|\n|^)(?:[^'"])*?(?:'(?:[^\r\n\\']|\\'|[\\]{2})*'|"(?:[^\r\n\\"]|\\"|[\\]{2})*")*?(?:[^'"])*?(\/\*(?:[\s\S]*?)\*\/|\/\/.*)/g
Последняя группа (все остальные отброшены) основана на ответе Райана. Пример здесь.
Это предполагает, что код хорошо структурирован и действителен javascript.
Примечание. Это не было протестировано на плохо структурированном коде, который может быть или не быть восстановлен в зависимости от собственной эвристики двигателя javascript.
Примечание: это должно выполняться для действительного javascript < ES6, однако, ES6 позволяет многострочные строковые литералы, и в этом случае это регулярное выражение почти наверняка сломается, хотя этот случай не был протестирован.
Однако по-прежнему можно сопоставить что-то, что выглядит как комментарий внутри литерала регулярного выражения (см. комментарии/результаты в примере выше).
Я использую вышеупомянутый захват после замены всех литералов регулярного выражения, используя следующий полный захват, извлеченный из es5-lexer здесь и здесь, как указано в Майк Самуэль, ответьте на этот вопрос:
/(?:(?: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
Для полноты см. также это тривиальное оговорка.
Если вы нажмете на ссылку ниже, вы найдете удаление комментария script, написанное в regex.
Это 112 строк кода, которые работают вместе, также работает с mootools и Joomla и drupal и другими сайтами cms. Протестировал его на 800 000 строк кода и комментариев. работает отлично. Это также выбирает множественные скобки (abc (/nn/('/xvx/')) "//строка тестирования" ) и комментарии, которые находятся между двоеточиями и защищают их. 23-01-2016..! Это код с комментариями в нем.!!!!
В простом простом регулярном выражении JS это:
my_string_or_obj.replace(/\/\*[\s\S]*?\*\/|([^:]|^)\/\/.*$/gm, ' ')
немного проще -
это работает также для многострочных - (<!--.*?-->)|(<!--[\w\W\n\s]+?-->)
Интересно, это был вопрос с подвохом, который профессор задал студентам? Зачем? Потому что мне кажется, что это невозможно сделать с помощью регулярных выражений в общем случае.
Ваш (или тот, кто его кодирует) может содержать действительный JavaScript, например:
let a = "hello /* ";
let b = 123;
let c = "world */ ";
Теперь, если у вас есть регулярное выражение, которое удаляет все между парой /* и */, это нарушит код выше, это также приведет к удалению исполняемого кода в середине.
Если вы попытаетесь создать регулярное выражение, которое не будет удалять комментарии, содержащие кавычки, вы не сможете удалить такие комментарии. Это относится к одинарным, двойным и обратным кавычкам.
Вы не можете удалить (все) комментарии с помощью регулярных выражений в JavaScript, мне кажется, возможно, кто-то может указать способ, как это сделать для случая выше.
Что вы можете сделать, это создать небольшой синтаксический анализатор, который просматривает код за символом и знает, когда он находится внутри строки и когда он находится внутри комментария, а когда он находится внутри комментария внутри строки и так далее.
Я уверен, что есть хорошие парсеры JavaScript с открытым исходным кодом, которые могут это сделать. Может быть, некоторые из упаковочных и минимизирующих инструментов могут сделать это и для вас.
Для комментария блока: https://regex101.com/r/aepSSj/1
Соответствует символу косой черты (\1
), только если за символом косой черты следует звездочка.
(\/)(?=\*)
возможно сопровождается другой звездочкой
(?:\*)
затем следует первая группа совпадений или ноль или более раз от чего-то... может быть, не помнить совпадения, но захватить как группу.
((?:\1|[\s\S])*?)
сопровождаемый звездочкой и первой группой
(?:\*)\1
Для блочного и/или встроенного комментария: https://regex101.com/r/aepSSj/2
где |
означает или и (?=\/\/(.*))
захватывать что-либо после любого //
или https://regex101.com/r/aepSSj/3, чтобы захватить третью часть тоже
Я тоже искал быстрое решение Regex, но ни один из ответов не дал результатов на 100%. Каждый из них в конечном итоге нарушает исходный код, в основном из-за комментариев, обнаруженных внутри строковых литералов. Например
var string = "https://www.google.com/";
становится
var string = "https:
Для удобства тех, кто пришел из Google, я написал короткую функцию (на Javascript), которая достигает того, чего не может сделать Regex. Изменить для любого языка, который вы используете для анализа Javascript.
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;
}
2019:
Все ответы приходят с падением, поэтому я пишу что-то, что просто работает, попробуйте:
function scriptComment(code){
const savedText = [];
return code
.replace(/(['"']).*?\1/gm,function (match) {
var i = savedText.push(match);
return (i-1)+'###';
})
// remove // comments
.replace(/\/\/.*/gm,'')
// now extract all regex and save them
.replace(/\/[^*\n].*\//gm,function (match) {
var i = savedText.push(match);
return (i-1)+'###';
})
// remove /* */ comments
.replace(/\/\*[\s\S]*\*\//gm,'')
// remove <!-- --> comments
.replace(/<!--[\s\S]*-->/gm, '')
.replace(/\d+###/gm,function(match){
var i = Number.parseInt(match);
return savedText[i];
})
}
var cleancode = scriptComment(scriptComment.toString())
console.log(cleancode)
Основываясь на вышеуказанных попытках и использовании UltraEdit, в основном Abhishek Simon, я нашел, что это работает для встроенных комментариев и обрабатывает все символы в комментарии.
(\s\/\/|$\/\/)[\w\s\W\S.]*
Это соответствует комментариям в начале строки или пробелу перед //
//public static final Строка LETTERS_WORK_FOLDER = "/Письма/Сформирован/работа";
но не
"http://schemas.us.com.au/hub/' > " +
так что это не хорошо для чего-то вроде
if (x) {f (x)}//где f - некоторая функция
он просто должен быть
if (x) {f (x)}//где f - функция