【问题标题】:How to differentiate between standard-inputs (via pipe and via prompt) in NodeJS?如何区分 NodeJS 中的标准输入(通过管道和提示)?
【发布时间】:2020-04-06 01:16:45
【问题描述】:

我的目标:将标准输入从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-

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

【问题讨论】:

    标签: node.js stdin prompt


    【解决方案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!
    

    【讨论】:

    • 谢谢。但问题是:该命令实际上并不像echo "abcdefhiy" | node input.js --accept 那样简单。它更像node thisruns15minutes.js | node input.js。所以我不希望用户使用附加参数再次运行整个事情..
    • 那么,恐怕答案就是“你不能那样做”。如果您选择通过管道将输入输入标准输入,则您也不能接受键盘输入。
    【解决方案2】:

    answer given by Tom Mettam 不太对。

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

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

    我发现最简单的方法是使用 Node 包 ttys,这非常简单,但我不必再次编写相同的代码。

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-29
      • 1970-01-01
      • 1970-01-01
      • 2014-01-04
      • 2018-08-10
      • 2022-07-05
      • 2014-07-10
      相关资源
      最近更新 更多