文章目錄
- 問題
- 回答
- 1. 使用 Here Document
- 2. 使用 echo 管道傳遞
- 3. 使用文件描述符
- 4. 使用 expect 工具
- 參考
問題
我有一個 Bash 腳本,它使用 read
命令以交互方式讀取命令參數,例如 yes/no
選項。是否有一種方法可以在非交互式腳本中調用這個腳本,并將默認選項值作為參數傳遞?
我不止需要向交互式腳本傳遞一個選項。
回答
如果你的腳本是通過 read
命令在交互式環境下讀取命令參數,并且你希望在非交互式腳本中傳遞參數,那么你可以使用以下幾種方法來模擬交互式輸入:
1. 使用 Here Document
Here Document 可以用來傳遞多行輸入到腳本:
bash your-interactive-script.sh <<EOF
answer1
answer2
answer3
EOF
其中 answer1
, answer2
, 和 answer3
是對應于腳本中每一個 read
提示的輸入。
2. 使用 echo 管道傳遞
可以通過 echo
命令和管道來傳遞輸入值:
echo -e "answer1\nanswer2\nanswer3" | bash your-interactive-script.sh
在這里,-e
會啟用對反斜杠轉義的解釋,\n
用于模仿輸入鍵(ENTER)的效果。
3. 使用文件描述符
還可以使用文件描述符來模擬交互式輸入:
exec 3< <(echo -e "answer1\nanswer2\nanswer3")
./your-interactive-script.sh <&3
exec 3<&-
在這里,打開了一個文件描述符 3
,并將其與提供輸入的進程替換關聯起來。你的腳本從該文件描述符中讀取內容,而不是從標準輸入(stdin)中讀取。
最后使用命令 exec 3<&-
關閉這個文件描述符,這樣可以防止資源泄露,并確保這個文件描述符可以在腳本或程序的后續部分重新使用。
在 Bash 腳本中,exec
命令用于執行命令并在當前 shell 環境中改變 shell 的行為。文件描述符是用于訪問文件和流的小的、非負整數。常見的文件描述符包括 0
(標準輸入 stdin)、1
(標準輸出 stdout)和 2
(標準錯誤 stderr)。
下面是這條命令的一部分解釋:
-
exec 3< ...
:這個命令會打開一個文件或者創建一個輸入流,并將它分配給文件描述符3
。當你讀取文件描述符3
時,你實際上會從這個文件或流中讀取數據。 -
<&-
:這是用來關閉文件描述符的語法。具體到exec 3<&-
,這條命令會關閉之前分配給文件描述符3
的文件或流。
總的來說,exec 3< <(command)
會創建一個新的文件描述符 3
,并從 command
命令產生的輸出中讀取數據。當你完成使用這個文件描述符后,使用 exec 3<&-
就可以關閉這個文件描述符,這樣可以防止資源泄露,并確保這個文件描述符可以在腳本或程序的后續部分重新使用。
測試截圖:
4. 使用 expect 工具
對于需要等待特定提示或需要更多控制的復雜場景,可以使用 expect
工具:
#!/usr/bin/expect -fspawn ./your-interactive-script.sh
expect "第一次提示"
send "answer1\r"
expect "第二次提示"
send "answer2\r"
expect "第三次提示"
send "answer3\r"
interact
你可以用以下命令來安裝 expect
:
sudo apt-get install expect # Debian/Ubuntu 系統
或者
sudo yum install expect # CentOS/RHEL 系統
根據你的腳本輸入場景的復雜程度來選擇最合適的方法。如果只是一系列簡單的輸入,方法 1 和 2 可能是最簡便的。但是,如果腳本需要更復雜的交互,expect
可能更合適。
#!/usr/bin/expect -fspawn ./interactive-script.sh
expect "name"
send "Bob\r"
expect "age"
send "17\r"
interact
測試截圖:
總之,根據你的腳本輸入場景的復雜程度來選擇最合適的方法。如果只是一系列簡單的輸入,方法 1 和 2 是最簡便的。但是,如果腳本需要更復雜的交互,expect 更合適。
參考
- stackoverflow question 14392525
- Here-Documents
- man expect
相關閱讀:
- sh和Bash的區別
- 2>&1是什么意思
- 如何使用bash腳本并行運行多個程序
- 為什么要使用xargs命令
- 在shell程序里如何從文件中獲取第n行
- 如何用命令行將文本每兩行合并為一行?