Comment lire stdin ligne par ligne dans Node

Je cherche à traiter un fichier texte avec un noeud en utilisant un appel en 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 de saisie peut être oubliée.

En utilisant l’écouteur on-data de stdin, j’obtiens la taille de la vapeur d’entrée par octet, je l’ai donc configurée.

 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 une manière plus élégante de le faire?

Vous pouvez utiliser le module readline pour lire stdin ligne par ligne:

 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 spécifiquement conçu pour fonctionner avec un terminal ( proccess.stdin.isTTY === true ). Il y a beaucoup de modules qui fournissent une fonctionnalité divisée pour les stream génériques, comme le partage . Cela rend les choses très faciles:

 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.toSsortingng()); 
 #!/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); 

Dans mon cas, le programme (elinks) a retourné des lignes qui semblaient vides, mais en fait il y avait des caractères de terminal spéciaux, des codes de contrôle de couleur et un retour arrière, donc les options de grep présentées dans d’autres réponses ne fonctionnaient pas. J’ai donc écrit ce petit script dans Node.js. J’ai appelé le fichier tight , mais c’est juste 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) }) 

partager pour les autres:

lire le stream ligne par ligne, devrait être bon pour les gros fichiers transféré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{ if(buffer.length) var str=buffer.join(''); buffer.length=0; on_line(str,()=>{ ////after end console.error('done') ////end after end }); }); readStream.resume();