JavaScript 分割字符串并读取每一行

7

我需要循环遍历一个包含多个换行符的大字符串,并读取每一行以查找字符。虽然我可以采用以下方法,但我感觉它并不是很高效,因为这个大字符串中可能会有超过5000个字符。

var str = largeString.split("\n");

然后将字符串作为数组循环

我不能使用jQuery,只能使用简单的JavaScript。

还有其他有效的方法吗?


嗯...你可以使用Web Worker,在后台解析字符串。http://www.w3schools.com/html/html5_webworkers.asp - StaleMartyr
使用正则表达式怎么样? - l2mt
5
这应该可以很好地运作 - 没有明显的更简单的方法。对于现代计算机,即使是智能手机,5000个字符也不算什么。您是否有证据表明这个速度过慢? - jfriend00
5000只是我期望的最小数字,但它也可能达到100000个字符。我意识到没有其他有效的方法来实现这一点。例如,在Java中,有StringReader可以用于此目的。 - nixgadget
6个回答

6
您可以始终使用 indexOfsubstring 来获取字符串中的每一行。
var input = 'Your large string with multiple new lines...';
var char = '\n';
var i = j = 0;

while ((j = input.indexOf(char, i)) !== -1) {
  console.log(input.substring(i, j));
  i = j + 1;
}

console.log(input.substring(i));

编辑 在回答之前我没有看到这个问题已经很老了。#失败

编辑2 修正代码以输出最后一个换行符后的文本行 - 感谢 @Blaskovicz


作为一个在2017年也有同样问题的人,我很高兴您发表了这个答案,尽管这是一个旧问题,但这是目前最好的答案。 - osvein
1
此外,对于阅读此内容的人,请记住,如果没有结束分隔符,这种方法不会获取尾随字符,就像 input.split(char) 一样。如果您需要执行此操作,只需检查 input.length === i 是否成立(表示没有尾随字符)。 - Blaskovicz

2

对于现代JavaScript引擎来说,5000并不是很高的负载。当然,这也取决于每次迭代所做的操作。为了清晰起见,建议使用eol.split[].forEach

eol是一个npm包。在Node.js和CommonJS中,您可以通过npm install eol进行安装,并使用require引用它。在ES6捆绑器中,您可以使用import。否则,通过<script>加载eol是全局的。

// Require if using Node.js or CommonJS
const eol = require("eol")

// Split text into lines and iterate over each line like this
let lines = eol.split(text)
lines.forEach(function(line) {
  // ...
})

第一行产生异常:未捕获的引用错误:require未定义。 - Leonid Mednikov
同时,split的工作方式与示例完全相反。正确的版本是:string.split(symbolForSplitting)。 - Leonid Mednikov
@LeonidMednikov的回答已经澄清了。require是用于Node.js或CommonJS的,否则请跳过该行。eol.split是一个不同于"".split的库方法。下次在不理解的情况下给出反对票之前,请考虑提出问题:) - ryanve

2

如果您正在使用NodeJS,并且有一个大字符串需要逐行处理:

最初的回答:

const Readable = require('stream').Readable
const readline = require('readline')

promiseToProcess(aLongStringWithNewlines) {
    //Create a stream from the input string
    let aStream = new Readable();
    aStream.push(aLongStringWithNewlines);
    aStream.push(null);  //This tells the reader of the stream, you have reached the end

    //Now read from the stream, line by line
    let readlineStream = readline.createInterface({
      input: aStream,
      crlfDelay: Infinity
    });

    readlineStream.on('line', (input) => {
      //Each line will be called-back here, do what you want with it...
      //Like parse it, grep it, store it in a DB, etc
    });

    let promise = new Promise((resolve, reject) => {
      readlineStream.on('close', () => {
        //When all lines of the string/stream are processed, this will be called
        resolve("All lines processed");
      });
    });

    //Give the caller a chance to process the results when they are ready
    return promise;
  }

0
function findChar(str, char) {
    for (let i = 0; i < str.length; i++) {
        if (str.charAt(i) == char) {
            return i
        }
    }
    return -1
}

0
你可以手动逐个字符地读取它并在获取换行符时调用处理程序。从 CPU 使用率的角度来看,这种方法不太可能更高效,但可能会占用更少的内存。但是,只要字符串小于几 MB,就不应该有影响。

-1

所以,你知道如何做,只是想确保没有更好的方法吗?嗯,我必须说你提到的方法就是它。不过,如果你正在寻找由特定字符分割的某些文本,你可能需要查找正则表达式匹配。可以在这里找到JS正则表达式参考。

如果你知道文本将如何设置,那么这将非常有用,类似于

var large_str = "[important text here] somethign something something something [more important text]"
var matches = large_str.match(\[([a-zA-Z\s]+)\])
for(var i = 0;i<matches.length;i++){
   var match = matches[i];
   //Do something with the text
}

否则,使用large_str.split('\n')方法并配合循环可能是最好的选择。

正则表达式很可能比.split()函数慢。而且,我认为这个方法不会起作用,因为\s包括\n,所以它不会在行边界处断开。 - jfriend00
考虑到我不知道他会如何寻找它,我给了他我所能提供的。如果我知道得更多,我可以提供更多帮助。我想他可以使用 .split() 来分割一些内容,然后对每个字符串使用正则表达式来查找他想要的任何内容。 - Jhecht

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接