2015-03-10 4 views
3

Я пытаюсь построить регулярное выражение, чтобы удалить все комментарии из javascript-кода, как однострочные (// ...), так и многострочные (/*..*/). Это то, что я придумал:Strip комментарии от javascript-файла

/\"[^\"]*\"|'[^']*'|(\/\/.*$|\/\*[^\*]*\*\/)/mg 

Описание: Как вы можете видеть, оно также ищет строковые литералы. Это связано с тем, что строковые литералы могут содержать контент, который в противном случае мог бы соответствовать шаблонам комментариев (например: location.href = "http://www.domain.com"; будет соответствовать одному комментарию строки). Поэтому я сначала помещаю строковые литералы в шаблоны альтернатив. Ниже приведены два шаблона, которые предназначены для улавливания одиночных комментариев и многострочных комментариев соответственно. Они заключены в одну группу захвата, так что я могу использовать string.replace (pattern, ""), чтобы удалить комментарии.

Я проверил выражение с паролем js-файлов и, похоже, работает. Мой вопрос в том, есть ли другие шаблоны, которые я должен искать, или если есть какие-то другие вещи, которые нужно рассмотреть (например, если в некоторых браузерах есть ограниченная поддержка регулярных выражений или альтернативной реализации, которые необходимо учитывать).

+0

* "Я пытаюсь создайте регулярное выражение, чтобы удалить все комментарии из javascript-кода ». * Вы не можете, это не проблема, регулярные выражения могут решить сами по себе. Вы можете получить * закрыть *, но там ** будет ** ситуация, когда он пойдет не так, возможно, разрушительным способом (например, удалением кода). –

+1

У вас есть примеры проблемных ситуаций, которые могут возникнуть? И любые предложения о том, что использовать в сочетании или вместо этого, чтобы разделить комментарии. – instantMartin

+0

Я думаю, T.J. означает проблемы, которые могут быть вызваны '' ',' \ ''(не заканчивается строка),' \\ '(' \\' 'завершает строку,' \\\ ''не делает) , '' ... "... '' (здесь '' 'не начинается или не заканчивается строка) и все комбинации символов' '', '' 'и' \ '. Так что на самом деле для каждой строки один из них имеет сначала строки литералов синтаксического анализа (или, может быть, в то же время комментарии разбираются), а затем удаляет комментарии, которые на самом деле не являются частями строк. – YakovL

ответ

1

Используйте C/C++ стиль комментария стриптизерша.
Ниже регулярное выражение делает эти вещи

  • Полоски и/**/и // Стили
  • Ручку стиля линий продолжения
  • Консервированными форматировании

Есть два формы регулярного выражения для сохранения формата:

  1. Горизонтальная табуляция \h и новая строка \n построить
  2. Space & вкладки [ \t] и \r?\n построить

Флаги многострочный и глобальная.
Замена группы захвата 2, $2 или \2.

Форма 1:

raw: ((?:(?:^\h*)?(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/(?:\h*\n(?=\h*(?:\n|/\*|//)))?|//(?:[^\\]|\\\n?)*?(?:\n(?=\h*(?:\n|/\*|//))|(?=\n))))+)|("(?:\\[\S\s]|[^"\\])*"|'(?:\\[\S\s]|[^'\\])*'|[\S\s][^/"'\\\s]*) 
delimited: /((?:(?:^\h*)?(?:\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\/(?:\h*\n(?=\h*(?:\n|\/\*|\/\/)))?|\/\/(?:[^\\]|\\\n?)*?(?:\n(?=\h*(?:\n|\/\*|\/\/))|(?=\n))))+)|("(?:\\[\S\s]|[^"\\])*"|'(?:\\[\S\s]|[^'\\])*'|[\S\s][^\/"'\\\s]*)/mg  

Форма 2:

raw: ((?:(?:^[ \t]*)?(?:/\*[^*]*\*+(?:[^/*][^*]*\*+)*/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|/\*|//)))?|//(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|/\*|//))|(?=\r?\n))))+)|("(?:\\[\S\s]|[^"\\])*"|'(?:\\[\S\s]|[^'\\])*'|(?:\r?\n|[\S\s])[^/"'\\\s]*) 
delimited: /((?:(?:^[ \t]*)?(?:\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\/(?:[ \t]*\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/)))?|\/\/(?:[^\\]|\\(?:\r?\n)?)*?(?:\r?\n(?=[ \t]*(?:\r?\n|\/\*|\/\/))|(?=\r?\n))))+)|("(?:\\[\S\s]|[^"\\])*"|'(?:\\[\S\s]|[^'\\])*'|(?:\r?\n|[\S\s])[^\/"'\\\s]*)/mg 

Expanded (отформатирован this) версия Форме 2:

(        # (1 start), Comments 
     (?: 
      (?:^[ \t]*)?     # <- To preserve formatting 
      (?: 
        /\*        # Start /* .. */ comment 
        [^*]* \*+ 
        (?: [^/*] [^*]* \*+)* 
       /        # End /* .. */ comment 
        (?:        # <- To preserve formatting 
         [ \t]* \r? \n          
         (?= 
          [ \t]*     
          (?: \r? \n | /\* | //) 
         ) 
       )? 
       | 
        //        # Start // comment 
        (?:        # Possible line-continuation 
         [^\\] 
        | \\ 
         (?: \r? \n)? 
       )*? 
        (?:        # End // comment 
         \r? \n        
         (?=        # <- To preserve formatting 
          [ \t]*       
          (?: \r? \n | /\* | //) 
         ) 
        | (?= \r? \n) 
       ) 
      ) 
     )+        # Grab multiple comment blocks if need be 
    )        # (1 end) 

|         ## OR 

    (        # (2 start), Non - comments 
     " 
     (?: \\ [\S\s] | [^"\\])*  # Double quoted text 
     " 
    | ' 
     (?: \\ [\S\s] | [^'\\])*  # Single quoted text 
     ' 
    | (?: \r? \n | [\S\s])   # Linebreak or Any other char 
     [^/"'\\\s]*      # Chars which doesn't start a comment, string, escape, 
             # or line continuation (escape + newline) 
    )        # (2 end) 
+0

Отлично. Большое спасибо. Это касается всего того, что меня беспокоило, - и еще кое-что в дополнение к предложениям по сохранению форматирования. Меня немного беспокоит время выполнения, поэтому я могу извлечь материал для форматирования сохранения, чтобы ускорить его (поскольку сохранение форматирования не является приоритет). Я также, вероятно, буду использовать более простое выражение (например, опубликованное ранее или что-то еще более простое) для поиска существования комментариев перед его запуском (так что файлы/разделы без комментариев в них могут быть пропущены). также определенно вдохновили, наконец, получить редактор регулярных выражений :-) – instantMartin

+0

@ MartinÖstlund - я не думаю, что сохраняющие конструкции форматирования немного замедляют производительность, поскольку он действует только на комментарии. – sln

+0

Вы совершенно правы @sln о том, чтобы не замедлить выполнение. Моя ошибка - я неправильно читаю регулярное выражение. – instantMartin

0

Посмотрите на этот код. Хотя это для PHP, я думаю, что шаблон правильный. Вы можете адаптировать шаблон для JavaScript.

https://gist.github.com/timw4mail/1338288

+0

Ссылка ведет к html minifier - я ищу, чтобы отключать комментарии только от javascript. , Я благодарю вас за подсказку, поскольку министры, вероятно, являются хорошим местом для поиска. В конце концов, javascript-маркеры блокируют комментарии. – instantMartin

0

Есть возможность сделать это (не регулярное выражение чисто JavaScript), но с некоторыми ограничениями. Я сделал что-то «на лету» для вас (25 мин). Используемый метод заключается в синтаксическом анализе исходного файла. Результат правильный, если файл js верен и у вас нет 3 исключений.

Найти имплантация здесь: http://jsfiddle.net/ch14em6w/

Вот код ключевая часть:

//parse file input 
function displayFileLineByLine(contents) 
{ 
    var lines = contents.split('\n'); 
    var element = document.getElementById('file-content'); 
    var output = ''; 
    for(var line = 0; line < lines.length; line++){ 

     var normedline = stripOut(lines[line]); 
     if (normedline.length > 0) 
     { 
      output += normedline; 
     } 
    } 
    element.innerHTML = output; 
} 
// globa scope flag showing '/*' is open 
var GlobalComentOpen = false; 

//recursive line coments removal method 
function stripOut(stringline, step){ 
     //index global coment start 
     var igcS = stringline.indexOf('/*'); 
     //index global coment end 
     var igcE = stringline.indexOf('*/'); 
     //index inline coment pos 
     var iicP = stringline.indexOf('//'); 
     var gorecursive = false; 
     if (igcS != -1) 
     { 
      gorecursive = true; 
      if (igcS < igcE) { 
       stringline = stringline.replace(stringline.slice(igcS, igcE +2), ""); 
      } 
      else if (igcS > igcE && GlobalComentOpen) { 
       stringline = stringline.replace(stringline.slice(0, igcE +2), ""); 
       igcS = stringline.indexOf('/*'); 
       stringline = stringline.replace(stringline.slice(igcS, stringline.length), ""); 
      } 
      else if (igcE == -1){ 
       GlobalComentOpen = true; 
       stringline = stringline.replace(stringline.slice(igcS, stringline.length), ""); 
      } 
      else 
      { 
       console.log('incorect format'); 
      } 

     } 
     if (!gorecursive && igcE != -1) 
     { 
      gorecursive = true; 
      GlobalComentOpen = false; 
      stringline = stringline.replace(stringline.slice(0, igcE +2), ""); 
     } 
     if (!gorecursive && iicP != -1) 
     { 
      gorecursive = true; 
      stringline = stringline.replace(stringline.slice(iicP, stringline.length), ""); 
     } 
     if (!gorecursive && GlobalComentOpen && step == undefined) 
     { 
      return ""; 
     } 
     if (gorecursive) 
     { 
      step = step == undefined ? 0 : step++; 
      return stripOut(stringline, step); 
     } 
     return stringline; 
} 
+0

Спасибо за обширный ответ с рабочим решением. Я часто предпочитаю не регулярное выражение, поскольку они часто более прозрачные решения Regexp компактны, но их функционирование может быть несколько непрозрачным и прогнозировать. Однако в предлагаемом решении я не вижу, чтобы вы рассматривали проблему комментарии, встроенные в строковые литералы, такие как «http://www.domain.com», о которых я упоминаю в вопросе (или я что-то упускаю в своей интерпретации кода). – instantMartin

+0

Вы меня поймете, почему я это сделал, и вы правы, единственная проблема остается в комментариях в строковых литералах. Я знаю, как реализовать эти исключения, но, читая все здесь, я понимаю, что дело не в этом. Итак, ваш первоначальный вопрос является законным и в дополнение к тому, что вы там говорили. Есть несколько случаев, когда комментарии могут появляться, и ваша реализация regexp/JavaScript наиболее приоритетна для появления оболочки комментариев: priority1: ''/* ", priority2:" */", priority3:" // " – SilentTremor

Смежные вопросы