【问题标题】:Using read -p in a bash script that was executed from pipe在从管道执行的 bash 脚本中使用 read -p
【发布时间】:2023-12-19 07:38:02
【问题描述】:

我提前道歉 - 我没有完全理解我所问的背后的想法,无法理解为什么它不起作用(我不知道我需要学习什么)。我首先在堆栈交换中搜索了答案 - 我发现了一些似乎可能相关的信息,但没有很好地解释这些概念,以至于我理解了如何构建一个有效的解决方案。我一直在搜索谷歌,但没有找到任何以我理解的方式准确描述正在发生的事情的信息。任何可以帮助我理解正在发生的事情的背景概念的指导将不胜感激。

是否可以在从管道执行的 bash 脚本中获取用户输入?

例如:

wget -q -O - http://myscript.sh | bash

在脚本中:

read -p "Do some action (y/n): " __response
if [[ "$__response" =~ ^[Yy]$ ]]; then
   echo "Performing some action ..."
fi

据我了解,这是行不通的,因为 read 尝试从标准输入读取输入,而 bash 脚本当前正在“通过该管道执行”(我确信有一种更技术准确的方法来描述什么是发生,但我不知道如何)。

我找到了推荐使用的解决方案:

read -t 1 __response </dev/tty

但是,这也不起作用。

任何关于我需要理解以使其工作的概念,或解释为什么它不工作或解决方案将不胜感激。

【问题讨论】:

    标签: bash pipe wget stdin


    【解决方案1】:

    tty 解决方案有效。用这段代码测试一下,例如:

    $ date | { read -p "Echo date? " r </dev/tty ; [ "$r" = "y" ] && cat || echo OK ; }
    Echo date? y
    Sat Apr 12 10:51:16 PDT 2014
    $ date | { read -p "Echo date? " r </dev/tty ; [ "$r" = "y" ] && cat || echo OK ; }
    Echo date? n
    OK
    

    来自read 的提示出现在终端上,read 在决定是否回显日期之前等待响应。

    我在上面写的内容在两个关键方面与下面的内容不同:

    read -t 1 __response </dev/tty
    

    首先,选项-t 1read 提供一秒的超时时间。其次,该命令不提供提示。这两者的结合可能意味着,即使read简要要求输入,你也不知道。

    【讨论】:

    • 谢谢。完美运行。
    【解决方案2】:

    这不起作用的主要原因是,正如 OP 有效指出的那样,

    • 使用的| 将第一个命令的标准输出作为标准输入发送到第二个命令。在这种情况下,第一个命令是

      wget -q -O - http://myscript.sh
      

      通过管道将下载的脚本传递给它的解释器bash

    • 脚本中的read 语句使用相同的标准输入来获取其值。

    所以这就是它崩溃的地方,因为read 不等待您的输入,而是从它自己的脚本中获取它。示例:

    $ cat - <<EOF | bash 
    > set -x
    > read p
    > somecommand
    > echo \$p
    > EOF
    + read p
    + echo somecommand
    somecommand
    

    在这个例子中,我使用了一个通过管道传输到 bash 的 here-document。该脚本使用set -x 启用调试以显示正在发生的事情。如您所见,somecommand 从未执行,但实际上由read 读取并存储在变量p 中,然后由echo 输出(注意,$ 已被转义以避免此处的替换-文档)。

    那么我们怎样才能让它发挥作用呢?

    首先,永远不要通过管道传递给{ba,k,z,c,tc,}sh 之类的解释器。这是丑陋的,应该避免,即使它感觉很自然。最好的办法是使用它的任何选项:

    bash -c string: 如果存在-c 选项,则从字符串中读取命令。如果字符串后面有参数,则将它们分配给位置参数,以$0开头。

    $ bash -c "$(command you want to pipe)"
    

    这也适用于zshcshtcshkshsh 可能还有很多其他人。

    【讨论】:

      最近更新 更多