1

I need to know if it's possible to iterate through every word input through stdin into a program using JavaScript. If so, may I get any leads on how to do so?

Evan
  • 345
  • 1
  • 5
  • 14

2 Answers2

2

With Node:

var stdin = process.openStdin();
var buf = '';

stdin.on('data', function(d) {
    buf += d.toString(); // when data is received on stdin, stash it in a string buffer
                         // call toString because d is actually a Buffer (raw bytes)
    pump(); // then process the buffer
});

function pump() {
    var pos;

    while ((pos = buf.indexOf(' ')) >= 0) { // keep going while there's a space somewhere in the buffer
        if (pos == 0) { // if there's more than one space in a row, the buffer will now start with a space
            buf = buf.slice(1); // discard it
            continue; // so that the next iteration will start with data
        }
        word(buf.slice(0,pos)); // hand off the word
        buf = buf.slice(pos+1); // and slice the processed data off the buffer
    }
}

function word(w) { // here's where we do something with a word
    console.log(w);
}

Processing stdin is much more complicated than a simple string split because Node presents stdin as a Stream (which emits chunks of incoming data as Buffers), not as a string. (It does the same thing with network streams and file I/O.)

This is a good thing because stdin can be arbitrarily large. Consider what would happen if you piped a multi-gigabyte file into your script. If it loaded stdin into a string first, it would first take a long time, then crash when you run out of RAM (specifically, process address space).

By handling stdin as a stream, you're able to handle arbitrarily large input with good performance, since your script only deals with small chunks of data at a time. The downside is obviously increased complexity.

The above code will work on any size input and doesn't break if a word gets chopped in half between chunks.

josh3736
  • 139,160
  • 33
  • 216
  • 263
1

Assuming you're using an environment that has console.log and standard input is a string, then you can do this.

Input:

var stdin = "I hate to write more than enough.";

stdin.split(/\s/g).forEach(function(word){
    console.log(word)
});

Outputs:

I
hate
to
write
more
than
enough.
Larry Battle
  • 9,008
  • 4
  • 41
  • 55
  • In Node, this won't work -- at least not reliably. Node's `stdin` is a `Buffer`, not a string. – josh3736 Jul 27 '12 at 22:58
  • This is great. But I'll need stdin to equal whatever is typed through the keyboard. Thank you for the good head start! – Evan Jul 27 '12 at 22:58
  • @Evan see the following answer http://stackoverflow.com/questions/5006821/nodejs-how-to-read-keystrokes-from-stdin?answertab=votes#tab-top – travis Jul 27 '12 at 23:04
  • @travis I'm not using nodejs, nor have I ever used it. – Evan Jul 28 '12 at 00:06
  • Are you trying to run this through the browser? You can capture all key strokes with the keydown event to capture keyboard input. Otherwise there really is no stdin for the browser. – travis Jul 28 '12 at 00:13
  • I really just want this to work through anything it's capable of working through honestly. Browser, console, whatever it's capable of. As soon as it works I'm finished with it. Is it possible to do the above ignoring punctuation? – Evan Jul 28 '12 at 01:54
  • @Evan: Browsers don't have stdin. – josh3736 Jul 28 '12 at 05:40