Подтвердить что ты не робот

RegEx для соответствия/замены комментариев JavaScript (как многострочных, так и встроенных)

Мне нужно удалить все комментарии 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.

Спасибо.

4b9b3361

Ответ 1

попробуйте это,

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

должен работать:) enter image description here

Ответ 2

ПРИМЕЧАНИЕ. 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

Ответ 3

Я поставил 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 '';
}

Это возвращает все, что было записано в тексте цитируемой строки, и все, что содержится в литеральном выражении регулярного выражения, но возвращает пустую строку для всех комментариев.

Я знаю, что это чрезмерно и довольно сложно поддерживать, но, похоже, он работает для меня до сих пор.

Ответ 4

Это работает практически во всех случаях:

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.

См. http://github.com/aMarCruz/jspreproc

Ответ 5

Это уже давно очень полезно для первоначального вопроса, но, возможно, это поможет кому-то.

Основываясь на ответе @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

Для полноты см. также это тривиальное оговорка.

Ответ 6

Если вы нажмете на ссылку ниже, вы найдете удаление комментария script, написанное в regex.

Это 112 строк кода, которые работают вместе, также работает с mootools и Joomla и drupal и другими сайтами cms. Протестировал его на 800 000 строк кода и комментариев. работает отлично. Это также выбирает множественные скобки (abc (/nn/('/xvx/')) "//строка тестирования" ) и комментарии, которые находятся между двоеточиями и защищают их. 23-01-2016..! Это код с комментариями в нем.!!!!

Нажмите здесь

Ответ 7

В простом простом регулярном выражении JS это:

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

Ответ 8

немного проще -

это работает также для многострочных - (<!--.*?-->)|(<!--[\w\W\n\s]+?-->)

enter image description here

Ответ 9

Интересно, это был вопрос с подвохом, который профессор задал студентам? Зачем? Потому что мне кажется, что это невозможно сделать с помощью регулярных выражений в общем случае.

Ваш (или тот, кто его кодирует) может содержать действительный JavaScript, например:

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

Теперь, если у вас есть регулярное выражение, которое удаляет все между парой /* и */, это нарушит код выше, это также приведет к удалению исполняемого кода в середине.

Если вы попытаетесь создать регулярное выражение, которое не будет удалять комментарии, содержащие кавычки, вы не сможете удалить такие комментарии. Это относится к одинарным, двойным и обратным кавычкам.

Вы не можете удалить (все) комментарии с помощью регулярных выражений в JavaScript, мне кажется, возможно, кто-то может указать способ, как это сделать для случая выше.

Что вы можете сделать, это создать небольшой синтаксический анализатор, который просматривает код за символом и знает, когда он находится внутри строки и когда он находится внутри комментария, а когда он находится внутри комментария внутри строки и так далее.

Я уверен, что есть хорошие парсеры JavaScript с открытым исходным кодом, которые могут это сделать. Может быть, некоторые из упаковочных и минимизирующих инструментов могут сделать это и для вас.

Ответ 10

Для комментария блока: https://regex101.com/r/aepSSj/1

Соответствует символу косой черты (\1), только если за символом косой черты следует звездочка.

(\/)(?=\*)

возможно сопровождается другой звездочкой

(?:\*)

затем следует первая группа совпадений или ноль или более раз от чего-то... может быть, не помнить совпадения, но захватить как группу.

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

сопровождаемый звездочкой и первой группой

(?:\*)\1

Для блочного и/или встроенного комментария: https://regex101.com/r/aepSSj/2

где | означает или и (?=\/\/(.*)) захватывать что-либо после любого //

или https://regex101.com/r/aepSSj/3, чтобы захватить третью часть тоже

все в: https://regex101.com/r/aepSSj/8

Ответ 11

Я тоже искал быстрое решение 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;
}

Ответ 12

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)

Ответ 13

Основываясь на вышеуказанных попытках и использовании 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 - функция