Cómo leer de stdin línea por línea en nodo

Estoy tratando de procesar un archivo de texto con nodo usando una llamada de línea de comando como:

node app.js < input.txt

Cada línea del archivo debe procesarse individualmente, pero una vez procesada, la línea de entrada puede olvidarse.

Usando el oyente en-datos del stdin, recibo la entrada de vapor fragmentada por un tamaño de byte, así que configuré esto.

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

Pero esto parece tan descuidado. Tener que dar masajes alrededor del primer y último elemento de la matriz de líneas. ¿No hay una manera más elegante de hacer esto?

Puede usar el módulo readline para leer de stdin línea por línea:

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

readline está específicamente diseñado para funcionar con terminal (es decir, proccess.stdin.isTTY === true ). Hay muchos módulos que proporcionan funcionalidad dividida para transmisiones genéricas, como split . Hace las cosas súper fáciles:

 process.stdin.pipe(require('split')()).on('data', processLine) function processLine (line) { console.log(line + '!') } 
 // Work on POSIX and Windows var stdinBuffer = fs.readFileSync(0); // STDIN_FILENO = 0 console.log(stdinBuffer.toString()); 
 #!/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); 

En mi caso, el progtwig (enlaces) devolvió líneas que parecían vacías, pero de hecho tenían caracteres especiales de terminal, códigos de control de color y retroceso, por lo que las opciones grep presentadas en otras respuestas no me funcionaron. Así que escribí este pequeño script en Node.js. Llamé al archivo tight , pero eso es solo un nombre al azar.

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

Compartir para otros:

leer la secuencia línea por línea, debería ser bueno para los archivos de gran tamaño conectados a stdin, mi versión:

 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{ if(buffer.length) var str=buffer.join(''); buffer.length=0; on_line(str,()=>{ ////after end console.error('done') ////end after end }); }); readStream.resume();