2015-12-25 4 views
7

У меня есть большой действительный файл JavaScript (utf-8), из которого мне нужно извлечь все текстовые строки автоматически.Поиск текстовых строк в JavaScript

Для простоты файл не содержит блоков комментариев в нем, только действительный код JavaScript ES6.

После того, как я считаю возникновение ' или " или `, я должен сканировать конец текстового блока, где я застрял, учитывая все возможные варианты, как "'", '"',«\» " '\"', '", `\` `и т.д.

есть ли известно и/или повторное использование алгоритма для обнаружения конца действительного текстового блока ES6 JavaScript

ДОПОЛНЕНО-1: Мой файл JavaScript не просто большой, я также должен обрабатывать его как поток, в кусках, поэтому Regex абсолютно неприменим. хочу усложнить мой вопрос, упомянув совместные фрагменты кода, я сам это пойму, если у меня есть алгоритм, который может работать для одного фрагмента кода, который находится в памяти.

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

Примеры регулярных выражений, которые нарушают любой из методов обнаружения текста предложил до сих пор:

/'/ 
/"/ 
/\`/ 

Изучив этот вопрос ближе, прочитав это: How does JavaScript detect regular expressions?, я боюсь, что обнаружение регулярных выражений в JavaScript является совершенно новая игра с мячом, стоит отдельного вопроса, иначе она становится слишком сложной. Но я очень ценю, если кто-то может мне точку в правильном направлении, с этим вопросом ...

ДОПОЛНЕНО-3: После долгих исследований я обнаружил, с сожалением, что я не могу придумать алгоритм, который будет работать в моем потому что наличие регулярных выражений делает задачу невероятно сложной, чем первоначально предполагалось. В соответствии со следующим: When parsing Javascript, what determines the meaning of a slash?, определение начала и конца регулярных выражений в JavaScript является одной из самых сложных и запутанных задач. И без этого мы не можем понять, когда символы ', '' 'и `открывают текстовый блок или находятся внутри регулярного выражения.

+0

@connexo Я не могу использовать Regex в большом файле JavaScript. –

+0

Вы могли бы привести пример? – saruftw

+0

@ saru95 какой пример? Текстовой строки JavaScript? –

ответ

3

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

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

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

`foo${"bar"+`baz`}` 

Очевидными кандидатами на использование парсеров являются esprima и babel.

Кстати, что вы планируете делать с этими строками после их извлечения?

+0

Было бы более полезно, если бы вы были более конкретны в своих предложениях, например, начиная с этого: https://astexplorer.net/. Поймите, что для любого новичка, синтаксические анализаторы АСТ могут быть трудно найти и выяснить, какой из них использовать и почему. –

+0

Я почти не вижу, как я мог бы иметь более конкретный характер, чем предлагать esprima и babel. В Esprima есть удобная онлайн-песочница. –

+0

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

0

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

Учитывая строковый литерал "\n", вы ожидаете строку односимвольной, содержащей символ новой строки или обратные косые черты два символов и п?

  • В первом случае вам необходимо интерпретировать escape-последовательности точно так же, как JavaScript интерпретатор. Что вам нужно, это lexer для JavaScript, и многие люди уже запрограммировали этот кусок кода.
  • В последнем случае регулярное выражение должно распознавать escape-последовательности, такие как \x40 и \u2026, поэтому даже в этом случае вы должны скопировать код из существующего JavaScript-лексера.

См. https://github.com/douglascrockford/JSLint/blob/master/jslint.js, функция tokenize.

+0

Чтобы выразить это просто, как только я найду индекс символа открытия текста, например '' 'или' '' или \ ', мне нужно найти индекс соответствующего символа закрытия текста. И я не уверен что RegEx будет хорошим решением для больших файлов JavaScript. –

+0

Этот метод 'tokenize', кажется, составляет большую часть библиотеки, он огромен. Я надеялся на что-то более простое, если это возможно. –

-1

код Try ниже:

txt = "var z,b \n;z=10;\n b='321`1123`321321';\n c='321`321`312`3123`';" 
function fetchStrings(txt, breaker){ 
     var result = []; 
     for (var i=0; i < txt.length; i++){ 
     // Define possible string starts characters 
     if ((txt[i] == "'")||(txt[i] == "`")){ 
      // Get our text string; 
      textString = txt.slice(i+1, i + 1 + txt.slice(i+1).indexOf(txt[i])); 
      result.push(textString) 
      // Jump to end of fetched string; 
      i = i + textString.length + 1; 
     } 
     } 
     return result; 
    }; 

console.log(fetchStrings(txt)); 
+0

Если вы удалите'; 'в конец входной строки, алгоритм больше не работает ... –

+0

@ vitaly-t Спасибо, код обновлен, просто 'txt.slice (i + 1, -1)' заменен на 'txt.slice (i + 1)' Надеюсь, что это будет полезно для вас. –

+0

Вы определяете 'fetchStrings' для принятия аргумента' breaker', но никогда не используете его. Кроме того, будет ли он работать со строками типа '" foo \ "bar" '? –

-1

Могу ли я позволить вам проверить это самостоятельно? Я считаю, что вы сможете использовать это решение с кусками после нескольких настроек (например, сброс i до 0 для каждого нового фрагмента может стать хорошей отправной точкой). Я в порядке, чтобы продолжить работу над вашим вопросом, хотя я бы хотел, чтобы вы сказали мне, если я направляюсь в правильном направлении :-)

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

var strings = []; 
 
code(document.getElementsByTagName('script')[0].textContent, 0); 
 
document.write('<pre>' + JSON.stringify(strings, 0, 2) + '</pre>'); 
 

 
function code (text, i) { 
 
    if (i < text.length) { 
 
    var c = text.charAt(i); 
 
    if (/`|'|"/.test(c)) { 
 
     strings.push(''); 
 
     string(text, i + 1, text.charAt(i)); 
 
    } else if (c == '/') { 
 
     slash(text, i + 1); 
 
    } else { 
 
     code(text, i + 1); 
 
    } 
 
    } 
 
} 
 

 
function string (text, i, quote) { 
 
    if (i < text.length) { 
 
    var step, c = text.charAt(i); 
 
    if (c == quote) { 
 
     code(text, i + 1); 
 
    } else { 
 
     step = c == '\\' ? 2 : 1; 
 
     strings[strings.length - 1] += text.substr(i, step); 
 
     string(text, i + step, quote); 
 
    } 
 
    } 
 
} 
 

 
function slash (text, i) { 
 
    if (i < text.length) { 
 
    var c = text.charAt(i); 
 
    if (c == '/') { 
 
     singlelinecomment(text, i + 1); 
 
    } else if (c == '*') { 
 
     multilinecomment(text, i + 1, ''); 
 
    } else { 
 
     regex(text, i + 1); 
 
    } 
 
    } 
 
} 
 

 
function singlelinecomment (text, i) { 
 
    if (i < text.length) { 
 
    var c = text.charAt(i); 
 
    if (c == '\n') { 
 
     code(text, i + 1); 
 
    } else { 
 
     singlelinecomment(text, i + 1); 
 
    } 
 
    } 
 
} 
 

 
function multilinecomment (text, i, prev) { 
 
    if (i < text.length) { 
 
    var c = text.charAt(i); 
 
    if (prev == '*' && c == '/') { 
 
     code(text, i + 1); 
 
    } else { 
 
     multilinecomment(text, i + 1, c); 
 
    } 
 
    } 
 
} 
 

 
function regex (text, i) { 
 
    if (i < text.length) { 
 
    var c = text.charAt(i); 
 
    if (c == '/') { 
 
     code(text, i + 1); 
 
    } else { 
 
     regex(text, i + 1); 
 
    } 
 
    } 
 
}
<script> 
 
var s = ""; 
 
var r = /'allo'/; 
 
// "single line comment" 
 
var f = function(){ return '`a str\'ing`'; }; 
 
/** 'multi line' 
 
`comment` **/ 
 
var o = { "prop": "va\"'lue" }; 
 
var l = '\ 
 
    a\ 
 
    multi\ 
 
    line\ 
 
    string'; 
 
</script>

+0

Я немного поработал над определением правильного выражения, и это кажется невероятно сложной задачей, на самом деле одной из самых сложных задач при анализе JavaScript. Ваш код для этой части даже не близок. См. Ссылки: http://stackoverflow.com/questions/5519596/when-parsing-javascript-what-determines-the-meaning-of-a-slash и http://stackoverflow.com/questions/8334168/how-does -javascript-detect-regular-expressions –

+0

@ vitaly-t Снимая спецификацию языка, я дал понять, что вы подразумеваете под «запутанным» ... Я должен отказаться, очевидно, у меня недостаточно навыков/время для реализации полного парсера xD Удачи тогда :-) – leaf

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