नोड में लाइन द्वारा स्टडिन लाइन से कैसे पढ़ें


177

मैं कमांड लाइन कॉल की तरह नोड के साथ एक टेक्स्ट फ़ाइल संसाधित करना चाहता हूं:

node app.js < input.txt

फ़ाइल की प्रत्येक पंक्ति को व्यक्तिगत रूप से संसाधित करने की आवश्यकता होती है, लेकिन एक बार संसाधित होने पर इनपुट लाइन को भुलाया जा सकता है।

स्टड के ऑन-डेटा श्रोता का उपयोग करते हुए, मुझे बाइट के आकार से चिपकाया गया इनपुट स्टीम मिलता है इसलिए मैंने इसे सेट किया।

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

लेकिन यह इतना फूहड़ लगता है। लाइनों के पहले और अंतिम आइटम के चारों ओर मालिश करना। क्या ऐसा करने का अधिक सुरुचिपूर्ण तरीका नहीं है?

जवाबों:


207

स्टड लाइन से लाइन द्वारा पढ़ने के लिए आप रीडलाइन मॉड्यूल का उपयोग कर सकते हैं :

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

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

3
यह कंसोल में हाथ से इनपुट दर्ज करने के लिए अच्छी तरह से काम करता है, हालांकि, जब मैं किसी फाइल को कमांड में भेजता हूं तो फाइल को स्टडआउट भेजा जाता है। एक दोष? इस बिंदु पर रीडलाइन को अस्थिर माना जाता है।
मैट आर। विल्सन

1
मुझे लगता है कि आप सिर्फ process.stdoutएक अलग लेखन योग्य धारा में बदल सकते हैं - यह उतना ही सरल हो सकता हैoutput: new require('stream').Writable()
जेफ सीसन

3
दुर्भाग्य से, मुझे स्टडआउट की आवश्यकता है। मैंने इसे अपने प्रश्न से बाहर कर दिया, लेकिन मैं कोशिश कर रहा हूं कि मैं इस ऐप को प्रयोग करने लायक बना सकूं node app.js < input.txt > output.txt
मैट आर। विल्सन

जाहिरा तौर पर यह 'डिजाइन द्वारा' github.com/joyent/node/issues/4243#issuecomment-10133900 है । इसलिए मैंने कहा कि आपने जैसा कहा था और आउटपुट विकल्प को एक डमी लिखने योग्य स्ट्रीम प्रदान किया, फिर सीधे स्टडआउट स्ट्रीम में लिखा। मुझे यह पसंद नहीं है, लेकिन यह काम करता है।
मैट आर। विल्सन

13
ऐसा लगता है कि यदि आप terminal: falsecreateInterface में तर्क पास करते हैं , तो यह इस समस्या को हल करता है।
जेसनक्रॉफर्ड

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

3
क्या आप कुछ विवरण शामिल कर सकते हैं? पहले से ही एक उच्च श्रेणी के स्वीकृत उत्तर है
jhhoff02

2
यह मेरे लिए काम नहीं करता है (नोड v9.2.0, विंडोज)। Error: EISDIR: illegal operation on a directory, fstat at tryStatSync (fs.js: 534: 13) `
एलेक्साचेफी

2
नोड v6.11.2, OSX पर मेरे लिए काम किया।
टिफ़न

3
@AlexChaffee: विंडोज पर एक बग प्रतीत होता है (अभी भी v9.10.1 के रूप में मौजूद है) यदि कोई स्टडिन इनपुट नहीं है या यदि स्टड बंद है - तो इस GitHub मुद्दे को देखें । इसके अलावा, हालांकि, समाधान विंडोज पर काम करता है
mklement0

3
बहुत अच्छी तरह से काम करता है और अब तक सबसे छोटा है, ऐसा करने से इसे कम किया जा सकता हैfs.readFileSync(0).toString()
लोकलहोस्टदेव

56

readlineविशेष रूप से टर्मिनल (जो है process.stdin.isTTY === true) के साथ काम करने के लिए डिज़ाइन किया गया है । बहुत सारे मॉड्यूल हैं जो सामान्य धाराओं के लिए विभाजन कार्यक्षमता प्रदान करते हैं, जैसे विभाजन । यह चीजों को सुपर आसान बनाता है:

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

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

6
नहीं यह नहीं। यदि आप लाइन-बाय-लाइन नहीं पढ़ना चाहते हैं तो आपको इसकी आवश्यकता नहीं है
vkurchatkin

6
युक्ति: यदि आप सभी लाइनों को संसाधित करने के बाद कुछ कोड चलाना चाहते हैं, .on('end', doMoreStuff)तो पहले के बाद जोड़ें .on()। याद रखें कि यदि आप कथन के बाद सामान्यतः कोड लिखते हैं .on(), तो वह कोड किसी भी इनपुट को पढ़ने से पहले चलेगा, क्योंकि जावास्क्रिप्ट समकालिक नहीं है।
रोरी ओ'केन

14
#!/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

दूसरों के लिए साझा करना:

लाइन द्वारा स्ट्रीम लाइन पढ़ें, स्टड में पाइप की गई बड़ी फ़ाइलों के लिए अच्छा होना चाहिए, मेरा संस्करण:

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

मेरे मामले में कार्यक्रम (एलिंक) ने ऐसी लाइनें लौटा दीं जो खाली दिखती थीं, लेकिन वास्तव में विशेष टर्मिनल वर्ण, रंग नियंत्रण कोड और बैकस्पेस थे, इसलिए 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) 
})
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.