我只是在学习bash脚本。这是我第一次不得不将输出重定向到另一个程序,但我不知道该怎么做
我必须写一个脚本,连接一个GUI程序和零个、一个或两个程序——我需要两个玩家,都可以是计算机或人类。GUI从两个程序(或者人类,我指的是从stdin)获得输出。
让我们假设有一个人和一个comp_player。人工使用stdin发出命令,该命令必须重定向到运行GUI程序和运行comp_player,两者都需要输入。然后,comp_player的输出必须重定向到GUI(如果有第二个计算机播放器,也有必要将此输出重定向到第二个电脑播放器的输入)。转弯结束。
我知道如何创建一个文件来读写和重定向输入或输出。例如:
echo "anything" >&3
exec 3<>sometextfile
read line <&3
echo $line
但我不知道的是如何重定向,例如,我刚刚读到的一行,指向正在运行的程序,该程序期望输入并捕获其输出,我可以将其重定向到GUI和另一个程序。
我知道它并不像上面的代码那么简单,我必须使用一种名为命名管道的东西,但我试着阅读了一些教程,但我没能写出工作脚本。
你能给我一个脚本片段的例子吗,比如:
(gui程序和计算机播放器程序正在运行)
-从stdin 读取行
-将行"发送"到gui程序和comp_player的输入
-"读取"comp_player的输出并将其写入stdout,还将其"发送"到gui输入
命名管道是一种特殊类型的文件,用于连接两个完全独立的程序的输入和输出。可以把它想象成一个临时缓冲区,或者一个在两个互不了解的程序之间共享的数组。这使它们成为一个很棒的工具,可以在两个程序之间共享消息,并使它们能够非常有效地进行通信。
作为查看命名管道如何工作的简单测试,请打开同一目录中的两个端子,并在第一个端子中键入mkfifo mypipe
以创建文件。现在,要使用它,只需向它写入一些内容,例如:echo "A very important message" >mypipe
现在消息存储在管道文件中,您将看到终端被阻止,就好像echo
还没有完成一样。转到第二个终端并使用以下命令获取管道内容:cat mypipe
您将从第一个终端打印出存储在管道中的"非常重要的消息"。请注意,管道现在是空的,您根本无法从中再次获得消息。
现在您知道了命名管道是如何工作的,下面是一个关于三个玩家如何通信的非常简单的例子。请注意,我们不能为所有这些文件使用一个文件,相反,我们将创建单独的管道来通信player1和player2、player1与gui以及player2与gui。我猜gui程序是用另一种语言编写的,但我将把它留给你。
播放器1(人类)
player2pipe="pipe1"
guipipe="pipe2"
#First make sure we have our files
if [ ! -p $player2pipe ]; then
mkfifo $player2pipe
fi
if [ ! -p $guipipe ]; then
mkfifo $guipipe
fi
while true; do #Or until the game ends
echo -n "Do something: "
read move
# Send our move to the other two players
echo $move > $player2pipe
echo $move > $guipipe
playermove=$(cat $player2pipe) # Read other player's move from the pipe file. The execution will pause until there's something to read
# Do something about that move here
done
播放器2(电脑)
player1pipe="pipe1"
guipipe="pipe3"
if [ ! -p $player1pipe ]; then
mkfifo $player1pipe
fi
if [ ! -p $guipipe ]; then
mkfifo $guipipe
fi
while true; do
playermove=$(cat $player1pipe)
# Do something about that move here
move="A very good move made by a computer" #Obviously you will have to generate a new move
echo $move > $player1pipe
echo $move > $guipipe
done
GUI
player1pipe="pipe2"
player2pipe="pipe3"
if [ ! -p $player1pipe ]; then
mkfifo $player1pipe
fi
if [ ! -p $player1pipe ]; then
mkfifo $player1pipe
fi
while true; do #Or until the game ends
# Read other players' move from the pipe files. Notice the order here, if player2 moved before player1 the execution would be locked until the pipe is emptied
player1move=$(cat $player1pipe)
player2move=$(cat $player2pipe)
#Print out their move or whatever you need to do with it.
echo $player1move
echo $player2move
# Do whatever else you need to do about those moves
done
将这三个文件保存在同一目录中,并从三个不同的终端执行它们,以查看它们的工作方式。希望我能帮上忙。