如何在NodeJS中区分标准输入(通过管道和通过提示符)?

时间:2019-12-12 15:38:23

标签: node.js stdin prompt

我的目标是:将标准输入从echo传递到节点文件,并通过提示符要求更多输入。但是我需要知道哪个输入来自管道,哪个输入来自提示符。

节点文件 x.js 如下所示:

const readline = require("readline");

let rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout
});

rl.question("yes or no? (y/n)", answer => {
    console.log("-" + answer + "-");
    rl.close();
});

这一项有效(显示提示,我输入“ hello”并将其写入控制台):

> node x.js -hello-

但是这不起作用(没有提示。管道字符串只是写入控制台。):

> echo "abcdefgh" | node x.js -abcdefgh-

如何区分这两种标准输入?

2 个答案:

答案 0 :(得分:1)

实际上,您的问题比您想象的要糟-问题不在于管道输入和键盘输入之间的区别,而是可以同时接受两者。

通过管道传输数据时,您基本上是在说“ 这是我的输入”-该应用程序无法再捕获键盘输入,实际上,在读取了管道传输的数据后,stdin立即关闭。

您是否完全固执己见?好吧,这取决于您要做什么。按照您的示例,如果您想让用户在接受某些东西之前先确认它是可以的,则可以使用命令行参数:

var stdin = process.stdin;

if (stdin.setRawMode)
{
        // No data is being piped, so fall back to your existing code
        const readline = require("readline");

        let rl = readline.createInterface({
            input: process.stdin,
            output: process.stdout
        });

        rl.question("yes or no? (y/n)", answer =>
        {
            console.log("-" + answer + "-");
            rl.close();
        });
}
else
{
        // resume stdin in the parent process (node app won't quit all by itself

        stdin.resume();

        // on any data into stdin
        let receivedData = '';
        stdin.on('data', (data) => {
                receivedData += data;
        });
        stdin.on('end', () => {
                // Input will have a \n appended
                receivedData = receivedData.slice(0, -1);

                console.log('I received "' + receivedData + '".');
                const args = process.argv.slice(2);
                for(const arg of args)
                {
                        if (arg.toLowerCase() === '--accept')
                        {
                                console.log('Accepted the input!');
                                return;
                        }
                }
                console.log('Is this OK? If so, pass --accept as a parameter');
        });
}

它的工作原理如下:

~ # echo "abcdefhiy" | node input.js

I received "abcdefhiy".
Is this OK? If so, pass --accept as a parameter

~ # echo "abcdefhiy" | node input.js --accept

I received "abcdefhiy".
Accepted the input!

答案 1 :(得分:0)

answer given by Tom Mettam不太正确。

确实process.stdin被管道输入占用,这意味着您不能再将其用于键盘输入。

但这并不意味着您根本无法使用键盘输入。您可以使用process.stdin所依赖的基础TTY readStream。

我发现最简单的方法是使用Node软件包ttys,它非常简单,但是省去了我再次编写相同代码的麻烦。

我认为您将使用tty.stdintty.stdout作为readline接口的参数。然后,您仍然可以使用流程参数来访问管道中的内容。

我刚刚在一个非常相似的问题上发布了an answer to my own question,您可能会发现阅读这些内容对于实现目的很有帮助。