If you send a value to a node.js script through piping, you must listen for the readable
or data
event listeners available to the process
object. Using the data
event listener puts the stream into flowing mode automatically, but if you use the readable
event listener, you need to manually switch stdin to flowing mode by using process.stdin.read()
. When writing to another command or script, use process.stdout.write()
, as it's a writable stream.
Flowing mode
#!/usr/bin/env node
let chunks = "";
process.stdin.on("data", data => {
// Convert Buffer instance data to string
chunks += data.toString();
})
// Triggered when there is no more data to read
process.stdin.on("end", () => {
// Pipe out the data 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();
// Will be null if there is no more data to read
if (flowingMode)
chunks += flowingMode.toString();
})
process.stdin.on("end", () => {
process.stdout.write(chunks);
})
To simplify handling of readable
and data
events:
#!/usr/bin/env node
process.stdin.pipe(process.stdout);
To execute logic on the end
event listener trigger:
#!/usr/bin/env node
process.stdin.pipe(process.stdout, { end: false });
process.stdin.on("end", () => /* your logic here */);
Example usage when handling the end
event:
#!/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