【问题标题】:why read in bash seems to write on the standard input为什么在 bash 中读取似乎写在标准输入上
【发布时间】:2022-01-21 17:20:46
【问题描述】:

我真的很困惑,我不知道发生了什么,所以我不确定要问什么:/

我打算使用 this question 在 bash 脚本中将输入发送到程序的标准输入(我希望 program.c 在标准输入上读取并打印它读取的内容,我使用 readline 做到这一点没有问题,我希望scrit.shprogram.c 将读取的内容发送到stdin,而我正在以一种复杂的方式进行操作,当我意识到我的代码中间带有read 的while 循环已经完成了这项任务时,我不知道为什么!)

所以它不需要我故意向 STDIN 发送任何东西(我显然这样做,但在编写这个循环时这不是我的意图),但我不明白发生了什么

这是它的外观:我使用 bash 脚本调用 program.c,它使用 readline 读取标准输入并打印它。我在下面写的 script.sh 绝对不应该适用于我所理解的(不多),但它(几乎)可以!

program.c:

#include <unistd.h>
#include <stdlib.h>
#include <readline/readline.h>

int main(void)
{
    char    *line_input;

    line_input = readline("[myPrompt]> ");
    if (!line_input)
    {
        write(1, "exit\n", 5);
        exit(0);
    }
    write(1, line_input, strlen(line_input));
    write(1, "\n", 1);
    return (0);
}

script.sh:

#!/bin/bash

VAR="\
one
two"

while read -r line
do
    echo "line: $line"
    ./program
done < <(echo "$VAR")

和输出:

line: one
[myPrompt]> two
two
[myPrompt]> exit

所以two这个词写在[myPrompt]&gt; 的右边,我猜是标准输入,它是由./program.c执行的

为什么?我从来没有发送过它,我只是在脚本的 while 循环中调用了./program,但它没有向标准输入发送任何内容

为什么它从第二个单词开始?

如果我不在循环中使用 read,我将无法重现此行为,因此它可能是相关的

【问题讨论】:

  • 你真的执行了./program.c吗? C源代码不能执行,需要编译。
  • why ? i never sent it 你认为&lt; &lt;(echo "$VAR") 是什么意思? why does it start at the second word ? 因为read -r line 读取第一行。我认为您可能错过了这样一个事实,即while stuff1; do stuff2. done &lt; this_here 将标准输入重定向到stuff1,但 重定向到stuff2 - 循环内的内容也将标准输入连接到重定向。
  • @Barmar ho,这是一个错误!我会编辑我的问题 ;) (./program.c -> ./program)
  • @KamilCuk 确实我完全错过了这个事实:) 你在评论中解释了一切,这可能是公认的回答

标签: bash stdin


【解决方案1】:

&lt; &lt;(echo "$VAR") 使用进程替换将循环的标准输入重定向到echo "$VAR" 命令的输出。它影响整个循环,而不仅仅是read -r line 行。

./program 继承自 stdin,因此它也从进程替换中读取。 read -r line 读取第一行,然后readline() 中的./program 读取第二行。

因为readline() 用于交互式输入,它会在读取输入时回显输入。这就是您在提示行上看到它的原因,如果您以交互方式响应,您会在此处看到它。

如果希望程序从终端读取而不是输入重定向,可以重定向到/dev/tty

#!/bin/bash

VAR="\
one
two"

while read -r line
do
    echo "line: $line"
    ./program </dev/tty
done < <(echo "$VAR")

您还可以保存脚本继承的原始标准输入,然后重定向到该标准输入。

#!/bin/bash

VAR="\
one
two"

while read -r line
do
    echo "line: $line"
    ./program.c <&3
done 3<&0 < <(echo "$VAR")

顺便说一句,您可以使用此处的字符串,而不是使用进程替换:&lt;&lt;&lt;"$VAR"

【讨论】:

  • 很酷的提示,这里的字符串:)
  • 谢谢!它清楚地解释了为什么program.c 只阅读第二行!但它错过了为什么program.c 在标准输入上的解释(正如@KamilCuk cmets 所解释的那样)(现在我明白&lt; &lt;("$VAR") 做了什么,这似乎很明显,但不是当我问的时候),如果你添加那个我可以将其标记为已接受的答案 :) 顺便说一句,我的问题不清楚,我对其进行了编辑,我知道为什么 program.c 在标准输入上收到某些内容时会打印提示和命令,但我不明白为什么收到它(这就是我想要的)!
  • 我在答案中添加了第一段,这能回答你的问题吗?
  • 那更好是的,谢谢,@KamilCuk 补充了一个重要的观点:stdin 的重定向发生在整个循环、它的条件和它的内容上,我认为这对于理解发生了什么很重要?
猜你喜欢
  • 1970-01-01
  • 2016-03-22
  • 2019-09-01
  • 1970-01-01
  • 1970-01-01
  • 2012-04-25
  • 2015-10-08
  • 2013-03-18
  • 1970-01-01
相关资源
最近更新 更多