web-dev-qa-db-fra.com

Comment lire depuis stdin ligne par ligne dans Node

Je cherche à traiter un fichier texte avec noeud en utilisant un appel de ligne de commande comme:

node app.js < input.txt

Chaque ligne du fichier doit être traitée individuellement, mais une fois traitée, la ligne en entrée peut être oubliée.

En utilisant le programme d’écoute sur les données du stdin, l’entrée Steam est fragmentée par une taille en octets et je la configure.

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

Mais cela semble tellement bâclé. Avoir à masser autour du premier et du dernier élément du tableau de lignes. N'y a-t-il pas un moyen plus élégant de faire cela?

116
Matt R. Wilson

Vous pouvez utiliser le module readline pour lire ligne par ligne 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);
})
145
levi

readline est spécialement conçu pour fonctionner avec un terminal (c'est-à-dire process.stdin.isTTY === true). De nombreux modules fournissent des fonctionnalités de partage pour les flux génériques, tels que split . Cela rend les choses super faciles:

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

function processLine (line) {
  console.log(line + '!')
}
47
vkurchatkin
// Work on POSIX and Windows
var stdinBuffer = fs.readFileSync(0); // STDIN_FILENO = 0
console.log(stdinBuffer.toString());
28
Zealic
#!/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);
5
simonepri

partage pour les autres:

lire le flux ligne par ligne, devrait être bon pour les gros fichiers redirigés dans stdin, ma 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();
1
Shimon Doodkin

Dans mon cas, le programme (elinks) renvoyait des lignes qui semblaient vides, mais qui comportaient en fait des caractères de terminal spéciaux, des codes de contrôle de couleur et des espaces arrière; les options grep présentées dans d'autres réponses ne fonctionnaient donc pas pour moi. J'ai donc écrit ce petit script dans Node.js. J'ai appelé le fichier tight, mais ce n'est qu'un nom aléatoire.

#!/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) 
})
0
exebook