if you pipe out a value to a node.js script you have to listen to the readable or data event listener available to the process object. Using the data event listener places the stream straight into flowing mode, whenever you use the readable event listener you have to force stdin to flowing mode using process.stdin.read(). To write to another command or to another script you have to use process.stdout.write(), it's a writeable stream.
Flowing mode
#!/usr/bin/env node
let chunks = "";
process.stdin.on("data", data => {
// data is an instance of the Buffer object, we have to convert it to a string
chunks += data.toString();
})
// the end event listener is triggered whenever there is no more data to read
process.stdin.on("end", () => {
// pipe out the data to another command or write to a file
process.stdout.write(chunks);
});
Non Flowing mode
#!/usr/bin/env node
process.stdin.on("readable", () => {
const flowingMode = process.stdin.read();
// flowingMode will become null, whenever there is no more data to read
if ( flowingMode )
chunks += flowingMode.toString();
})
process.stdin.on("end", () => {
process.stdout.write(chunks);
})
To prevent your self all this stress, you can do something like the below if there is non logic on the readable or data event handler
#!/usr/bin/env node
process.stdin.pipe(process.stdout);
if you want to do something whenever the end event listener is triggered you should do this
#!/usr/bin/env node
process.stdin.pipe(process.stdout, { end: false } );
process.stdin.on("end", () => /* logic */ );
when the end event listener is triggered execute your code
#!/usr/bin/env node
let chunk = "";
process.stdin.on("data", data => {
chunk += data.toString();
});
process.stdin.on("end", () => {
chunk.replace(/^\s*[\r\n]/gm,"").split(/\s+/).forEach(function (s) {
process.stdout.write(
s === 'bob'
? 'boy'
: s === 'alicia'
? 'girl'
: s === 'cookie'
? 'dog'
: 'unknown');
});
});
> cat input.txt | ./prog.js > result.txt