Bash

為什麼在將腳本傳送到 bash 時,不能使用 read 從 stdin 中讀取?

  • April 5, 2019

我不是在尋找該問題的變通方法或解決方案。我很好,它在bash. 我只是不明白為什麼它不起作用。

我正在尋找一個深入的答案,為什麼以下腳本不起作用。以前所有的網際網路搜尋結果,包括來自 unix.stackexchange.com 的文章,都無法真正完全清除這一點。它與read讀取stdin哪個不起作用有關,因為stdin已經通過管道cat餵食“採取”(?)?bash

範例 bash 腳本test.sh

echo "Please say name:"
read NAME
echo "Hello $NAME"

方法 1 呼叫腳本bash test.sh

$ bash test.sh
Please say name:
XYZ
Hello XYZ
$

方法 2 通過管道執行腳本到bash

$ cat test.sh | bash
Please say name:
$

所以腳本立即返回提示,無需等待輸入甚至列印第二行。

確實從標準輸入讀取了read,但您讀取的是標準輸入的下一行 - 即echo "Hello $NAME". 讀完那行之後,沒有更多的輸入,因此沒有更多的命令要執行,腳本就結束了。

只有一個標準輸入流,您正嘗試將它用於程式碼和數據。這與互動式bash會話如何從您的鍵入中讀取命令、read響應以及您執行的任何其他命令想要使用標準輸入的方式相同。

如果我們在腳本末尾添加額外的一行,您會看到這種情況:

echo "Please say name:"
read NAME
echo "Hello $NAME"
printf 'name=%s\n' "$NAME"

這既提供了進一步的命令來查看腳本繼續執行,並向我們展示了讀入的內容NAME

Please say name:
name=echo "Hello $NAME"

您可以看到該變數逐字保存了腳本文件中寫入的內容 - 沒有發生變數插值、執行或擴展。


如果你想read從終端,這是可能的。可能工作的最簡單方法是從標準輸出而不是標準輸入(!)讀取,這可能連接到 TTY:

read NAME <&1

這將等待我輸入一些內容,然後繼續執行程序的其餘部分。您也可以使用/dev/tty$(tty)

引用自:https://unix.stackexchange.com/questions/510804