node.js 如何在Node中逐行读取stdin

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/20086849/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 16:18:47  来源:igfitidea点击:

How to read from stdin line by line in Node

node.jsstdin

提问by Matt R. Wilson

I'm looking to process a text file with node using a command line call like:

我希望使用如下命令行调用处理带有节点的文本文件:

node app.js < input.txt

node app.js < input.txt

Each line of the file needs to be processed individually, but once processed the input line can be forgotten.

文件的每一行都需要单独处理,但是一旦处理完输入行就可以忘记了。

Using the on-data listener of the stdin, I get the input steam chunked by a byte size so I set this up.

使用 stdin 的 on-data 侦听器,我将输入流按字节大小分块,因此我进行了设置。

process.stdin.resume();
process.stdin.setEncoding('utf8');

var lingeringLine = "";

process.stdin.on('data', function(chunk) {
    lines = chunk.split("\n");

    lines[0] = lingeringLine + lines[0];
    lingeringLine = lines.pop();

    lines.forEach(processLine);
});

process.stdin.on('end', function() {
    processLine(lingeringLine);
});

But this seems so sloppy. Having to massage around the first and last items of the lines array. Is there not a more elegant way to do this?

但这似乎太草率了。必须围绕行数组的第一个和最后一个项目进行按摩。没有更优雅的方法来做到这一点吗?

回答by levi

You can use the readlinemodule to read from stdin line by line:

您可以使用readline模块逐行从 stdin 读取:

var readline = require('readline');
var rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout,
  terminal: false
});

rl.on('line', function(line){
    console.log(line);
})

回答by Zealic

// Work on POSIX and Windows
var fs = require("fs");
var stdinBuffer = fs.readFileSync(0); // STDIN_FILENO = 0
console.log(stdinBuffer.toString());

回答by vkurchatkin

readlineis specifically designed to work with terminal (that is process.stdin.isTTY === true). There are a lot of modules which provide split functionality for generic streams, like split. It makes things super-easy:

readline专门设计用于与终端(即process.stdin.isTTY === true)一起使用。有很多模块为通用流提供拆分功能,例如split。它让事情变得超级简单:

process.stdin.pipe(require('split')()).on('data', processLine)

function processLine (line) {
  console.log(line + '!')
}

回答by simonepri

#!/usr/bin/env node

const EventEmitter = require('events');

function stdinLineByLine() {
  const stdin = new EventEmitter();
  let buff = "";

  process.stdin
    .on('data', data => {
      buff += data;
      lines = buff.split(/[\r\n|\n]/);
      buff = lines.pop();
      lines.forEach(line => stdin.emit('line', line));
    })
    .on('end', () => {
      if (buff.length > 0) stdin.emit('line', buff);
    });

  return stdin;
}

const stdin = stdinLineByLine();
stdin.on('line', console.log);

回答by Shimon Doodkin

shareing for others:

分享给他人:

read stream line by line,should be good for large files piped into stdin, my version:

逐行读取流,应该适用于通过管道输入标准输入的大文件,我的版本:

var n=0;
function on_line(line,cb)
{
    ////one each line
    console.log(n++,"line ",line);
    return cb();
    ////end of one each line
}

var fs = require('fs');
var readStream = fs.createReadStream('all_titles.txt');
//var readStream = process.stdin;
readStream.pause();
readStream.setEncoding('utf8');

var buffer=[];
readStream.on('data', (chunk) => {
    const newlines=/[\r\n]+/;
    var lines=chunk.split(newlines)
    if(lines.length==1)
    {
        buffer.push(lines[0]);
        return;
    }   

    buffer.push(lines[0]);
    var str=buffer.join('');
    buffer.length=0;
    readStream.pause();

    on_line(str,()=>{
        var i=1,l=lines.length-1;
        i--;
        function while_next()
        {
            i++;
            if(i<l)
            {
                return on_line(lines[i],while_next);
            }
            else
            {
                buffer.push(lines.pop());
                lines.length=0;
                return readStream.resume();
            }
        }
        while_next();
    });
  }).on('end', ()=>{
      if(buffer.length)
          var str=buffer.join('');
          buffer.length=0;
        on_line(str,()=>{
            ////after end
            console.error('done')
            ////end after end
        });
  });
readStream.resume();

回答by exebook

In my case the program (elinks) returned lines that looked empty, but in fact had special terminal characters, color control codes and backspace, so grepoptions presented in other answers did not work for me. So I wrote this small script in Node.js. I called the file tight, but that's just a random name.

在我的例子中,程序(elinks)返回的行看起来是空的,但实际上有特殊的终端字符、颜色控制代码和退格,所以grep其他答案中提供的选项对我不起作用。所以我用 Node.js 写了这个小脚本。我调用了 file tight,但这只是一个随机名称。

#!/usr/bin/env node

function visible(a) {
    var R  =  ''
    for (var i = 0; i < a.length; i++) {
        if (a[i] == '\b') {  R -= 1; continue; }  
        if (a[i] == '\u001b') {
            while (a[i] != 'm' && i < a.length) i++
            if (a[i] == undefined) break
        }
        else R += a[i]
    }
    return  R
}

function empty(a) {
    a = visible(a)
    for (var i = 0; i < a.length; i++) {
        if (a[i] != ' ') return false
    }
    return  true
}

var readline = require('readline')
var rl = readline.createInterface({ input: process.stdin, output: process.stdout, terminal: false })

rl.on('line', function(line) {
    if (!empty(line)) console.log(line) 
})