【问题标题】:Give output of one shell script as input to another using named pipes使用命名管道将一个 shell 脚本的输出作为另一个 shell 脚本的输入
【发布时间】:2023-06-12 04:21:01
【问题描述】:

我是 linux 新手,一直在编写一些初学者级别的 shell 脚本。 我想做的是写2个脚本。第一个脚本将读取用户的输入,第二个脚本将在循环中显示此输入,直到它检测到用户的“退出”。

这就是我编写 2 个 shell 脚本的方式。

文件1.sh:

read var1
echo $var1

文件2.sh:

while [ "$var2" != "exit" ]
do
  echo $1
  read var2
done

现在,我想使用命名管道将 File1.sh 的输出作为输入传递给 File2.sh 的 var1。我可能必须修改 File2.sh 中的代码,以便它接受来自命名管道的参数(因为输入将来自命名管道而不是 $1),但我完全不确定如何去做.

将 File1.sh 的输出作为命名管道的输入可以给出如下:

mkfifo pipe
./File1.sh > pipe

此命令一直要求输入,直到我使用 ctrl + c 中断。我不知道为什么会这样。 另外如何让 File2.sh 从这个管道中读取?

这是正确的吗?

pipe|./File2.sh

我对 linux 很陌生,但我在网上搜索了很多,甚至没有一个在 shell 脚本中执行此操作的示例。

【问题讨论】:

    标签: linux shell ubuntu ubuntu-14.04 named-pipes


    【解决方案1】:

    至于您最初的问题,从命名管道(或文件系统中的任何其他对象)读取的语法是

    ./File2.sh <pipe
    

    另外,您的脚本需要 echo "$var2" 使用正确的变量名称和双引号以防止值被通配符扩展、变量替换等。另请参阅 When to wrap quotes around a shell variable?

    your own answer 中的代码有几个新问题。

    • File1.sh 中,您显然试图声明变量pipe1,但赋值语法错误:等号周围不能有空格。因为您从不将此变量用于任何事情,所以这基本上是无害的(但会导致pipe1: command not found,当然这很烦人)。

    • File2.sh 中,while 循环的语法被彻底搞砸了;你放弃了readecho 仍然缺少围绕变量的引号;然后你反复重新打开管道。

    while [ "$input" != "exit" ]
    do
         read -r input
         echo "$input"
    done <pipe1
    

    将整个循环重定向一次会显着提高效率。

    还要注意选项-r 以防止read 对其读取的值执行任何解析。 (不幸的是,丑陋的默认行为是过去遗留下来的,如果不破坏现有脚本就无法修复。)

    【讨论】:

    • 1.空格,是的。我不知道它们很重要。 2. $input 周围的引号很重要,以防止变量替换和所有这些,我将在此阅读更多内容。知道了。 3. -r 据我所知,如果它检测到反斜杠,则不会解析该值并进行新的行更正。谢谢 :) 这真的很有帮助。我会改正的。
    【解决方案2】:

    首先在 File1.sh 中,echo var1 应该是echo $var1

    为了获得来自pipe 的输入,请尝试:

    ./File2.sh < pipe
    

    【讨论】:

    • 好的,但是我必须在 File.sh 代码中写什么?程序如何知道管道不是用户,而是为 var1 提供输入?
    • 您无需更改任何内容。这就是标准输入的美妙之处。该程序不需要知道它来自哪里。
    【解决方案3】:

    我就是这样解决的。 我犯的第一个错误是在程序之外声明管道。我所期待的是程序接受“管道”类型的输入参数的特殊方式。据我所知,这是错误的。

    您需要做的是在程序中声明管道。所以在读取程序中你所做的是,

    对于 File1.sh:

    pipe1=/Documents
    mkfifo pipe1
    cat > pipe1
    

    这会将用户的读取输入发送到管道。 现在,当管道打开时,它将继续接受输入。只有在管道打开时才能从管道中读取。所以你需要打开第二个终端窗口来运行第二个程序。

    对于 File2.sh:

    while("$input" != "exit")
    do
         read -r input < pipe1
         echo "$input"
    done
    

    因此,每当您在第一个终端窗口中输入一些字符串时,它都会反映在第二个终端窗口中,直到检测到“退出”。

    【讨论】:

    • 这仍然是不正确的。您的脚本包含几个语法错误。不过,您确实正确解决了重定向问题。
    • 代码确实执行了..你能指出语法错误吗?我必须再次重申,我是新手,我很想改正我犯的每一个错误。
    • 尝试shellcheck.net,就像bash tag wiki 中的介绍文本所建议的那样。 (虽然它没有捕捉到奇怪的while 语法。)
    • 你是对的.. 读错了.. 我打错了.. 我把它从我的最终代码中删除了.. 至于 while 语句,我在输入之前比较输入一个值,但它仍然可以正常工作而没有错误。
    • 否;括号导致input 的值被评估为命令。你的意思是while [ "$input" != "exit" ]——方括号而不是圆括号,括号旁边的空格很重要。