在JavaScript中查找文本string

我有一个有效的JavaScript文件(utf-8),我需要从中自动提取所有文本string。

为了简单起见,该文件中不包含任何注释块,只有有效的ES6 JavaScript代码。

一旦我find'"或“的事件,我应该扫描文本块的末尾,是所有可能的变化,如"'"'"' ,' “,”\“, '" ,”\“等。

有没有一个已知和/或可重复使用的algorithm来检测有效的ES6 JavaScript文本块的结束?

更新-1:我的JavaScript文件不只是大,我也必须作为一个stream块,处理它,所以正则expression式绝对不可用。 我不想让我的问题复杂化,提到联合的代码块,我会自己弄清楚,如果我有一个algorithm,可以为内存中的单一代码工作。

更新-2:我得到了这个工作最初,感谢这里给出的许多build议,但由于正则expression式再次卡住了。

正则expression式的例子,打破迄今为止build议的任何文本检测技术:

 /'/ /"/ /\`/ 

通过仔细研究这个问题,通过阅读: JavaScript如何检测正则expression式? ,恐怕在JavaScript中检测正则expression式是一个全新的球类游戏,值得单独的一个问题,否则就太复杂了。 但是,如果有人能够在这个问题上指出我的正确方向,我非常感激。

更新3:经过大量的研究后,我很遗憾地发现,我不能提出一个适用于我的情况的algorithm,因为正则expression式的存在使得任务比最初想象的要复杂得多。 根据以下内容: 当parsingJavaScript时,什么决定了斜杠的含义? ,确定JavaScript中正则expression式的开始和结束是最复杂和最复杂的任务之一。 没有它,我们不知道什么时候符号' ,'''和'打开一个文本块,或者它们是否在正则expression式中。

parsingJavaScript的唯一方法是使用JavaScriptparsing器。 即使你能够使用正则expression式,在一天结束的时候,他们还没有足够强大的力量去做你正在做的事情。

你可以使用几个现有的parsing器之一,这是非常容易使用,或者你可以写你自己的,简化,专注于string提取问题。 我很难想象你想写自己的parsing器,即使是简单的parsing器。 你会花更多的时间来写和维护它比你想象的要多。

例如,一个现有的parsing器将会处理类似于下面的内容,而不会冒汗。

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

parsing器使用的明显候选者是esprima和babel。

顺便说一下,一旦你提取这些string,你打算怎么做?

如果你只需要一个近似的答案,或者如果你想得到的string完全按照它们在源代码中出现的那样,那么正则expression式就可以完成这个工作。

鉴于string文字"\n" ,你期望一个单字符的string包含一个换行符或两个字符反斜杠和n?

  • 在前一种情况下,您需要像JavaScript解释器一样解释转义序列。 你需要的是JavaScript的词法分析器 ,许多人已经编写了这段代码。
  • 在后一种情况下,正则expression式必须识别\x40\u2026等转义序列,所以即使在这种情况下,您也应该从现有的JavaScript词法分析器复制代码。

请参阅https://github.com/douglascrockford/JSLint/blob/master/jslint.js ,函数tokenize

尝试下面的代码:

  txt = "var z,b \n;z=10;\nb='321`1123`321321';\nc='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)); 

我可以让你自己testing一下吗? 我相信,你应该能够使用这个解决scheme,经过一些调整(例如,重新设置为0为每个新的块可能是一个很好的起点)。 我可以继续处理你的问题,但是我希望你告诉我是否正朝着正确的方向前进:-)

此代码使用recursion来跟踪当前状态(代码,string,注释或正则expression式)。 我不熟悉处理大文件,因此恐怕会导致堆栈溢出。 作为一种解决方法,您可以将状态保存在全局variables中,并以迭代的方式完成所有这些工作。

 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>