首页 文章

如何在Node中逐行读取stdin

提问于
浏览
113

我正在寻找使用命令行调用处理节点的文本文件,如:

node app.js < input.txt

文件的每一行都需要单独处理,但一旦处理,输入行就会被遗忘 .

使用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);
});

但这似乎很草率 . 必须按线阵列的第一个和最后一个项目 . 有没有更优雅的方式来做到这一点?

6 回答

  • 46

    readline 专门设计用于终端(即 proccess.stdin.isTTY === true ) . 有许多模块为通用流提供分离功能,例如split . 它让事情变得非常简单:

    process.stdin.pipe(require('split')()).on('data', processLine)
    
    function processLine (line) {
      console.log(line + '!')
    }
    
  • 0
    // Work on POSIX and Windows
    var stdinBuffer = fs.readFileSync(0); // STDIN_FILENO = 0
    console.log(stdinBuffer.toString());
    
  • 140

    您可以使用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);
    })
    
  • 4
    #!/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);
    
  • 0

    在我的情况下,程序(elinks)返回看起来为空的行,但实际上有特殊的终端字符,颜色控制代码和退格,所以在其他答案中提供的 grep 选项对我不起作用 . 所以我在Node.js中写了这个小脚本 . 我调用了文件 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) 
    })
    
  • 22

    为他人分享:

    逐行读取流,应该是大型文件管道输入stdin,我的版本:

    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();
    

相关问题