Bash技巧:實例詳解 read 內置命令讀取用戶輸入的用法

在 bash 裏面可使用 read 內置命令來讀取用戶輸入。
當在 while 循環中不斷調用 read 命令,並打印一些提示字符,如 $#> 等,就能夠不斷接收用戶輸入,而後執行一些自定義的命令。
看起來就像是一個簡易的 shell。shell

下面主要是介紹 read 命令的常見用法,用來逐步實現一個簡易的 shell 效果。bash

read 命令介紹

在 bash 中,read 內置命令能夠讀取用戶的一行輸入,並對輸入內容進行單詞拆分,依次賦值給指定的變量。app

查看 help read 的說明以下:框架

read: read [-ers] [-a array] [-d delim] [-i text] [-n nchars] [-N nchars] [-p prompt] [-t timeout] [-u fd] [name ...]
Read a line from the standard input and split it into fields.

Reads a single line from the standard input, or from file descriptor FD if the -u option is supplied.
The line is split into fields as with word splitting, and the first word is assigned to the first NAME, the second word to the second NAME, and so on, with any leftover words assigned to the last NAME.less

Only the characters found in $IFS are recognized as word delimiters.
If no NAMEs are supplied, the line read is stored in the REPLY variable.ssh

Exit Status:
The return code is zero, unless end-of-file is encountered, read times out (in which case it's greater than 128), a variable assignment error occurs, or an invalid file descriptor is supplied as the argument to -u.函數

即,read 命令從標準輸入讀取到一行,每行內容以換行符結尾,可是讀取到的內容不包含行末的換行符。測試

對於讀取到的內容,會按照 bash 的 IFS 全局變量保存的分割字符把輸入行拆分紅多個單詞,把這些詞依次賦值給提供的變量。ui

若是所給的變量個數少於分割後的單詞數,最後一個變量被賦值爲剩餘的全部單詞。命令行

舉例說明以下:

$ read first second third last
1 2 3 4 5 678
$ echo $first, $second, $third, $last
1, 2, 3, 4 5 678
$ read input_line
This is a test input line.
$ echo $input_line
This is a test input line.

能夠看到,默認基於空格來拆分單詞。
所給的第一個 first 變量被賦值爲拆分後的第一個單詞。
第二個 second 變量被賦值爲拆分後的第二個單詞。
第三個 third 變量被賦值爲拆分後的第三個單詞。
最後一個 last 變量被賦值爲第三個單詞後的全部單詞。

顯然,只提供一個變量時,整個輸入行都會賦值給這個變量。
打印的 input_line 變量值能夠看到這一點。

使用 -p 選項指定提示字符串

執行 read 命令時,默認不打印提示字符串。
若是想要引導用戶輸入特定的內容,可使用 -p 選項來指定提示字符串。

查看 help read 對該選項的說明以下:

-p prompt
output the string PROMPT without a trailing newline before attempting to read

即,在 -p 選項後面跟着一個 prompt 字符串。
在讀取用戶輸入以前,會先打印這個 prompt 字符串,以做提示。
這個提示字符串後面不會換行,會跟用戶的輸入在同一行。

具體舉例說明以下:

$ read -p "Please input your mood today: " mood
Please input your mood today: happy
$ echo $mood
happy

在執行所給的 read 命令時,會先打印 「Please input your mood today: 」字符串,沒有換行,等待用戶輸入。
上面的 「happy」 是輸入的字符串,會被賦值給指定 mood 變量。

當使用 while 循環不斷調用 read 命令,且用 -p 選項指定 $ 字符時,看起來就像是一個簡易的 shell,能夠根據用戶輸入作一些處理,也能夠指定其餘字符,如 >#

假設有一個 tinyshell.sh 腳本,內容以下:

#!/bin/bash

while read -p "tinyshell> " input; do
    if [ "$input" == "l" ]; then
        ls
    elif [ "$input" == "quit" ]; then
        break
    else
        echo "Unknown input: $input"
    fi
done

該腳本在 while 循環中不斷調用 read 命令,使用 -p 選項設置提示字符串爲 「tinyshell> 」,DOS 命令行的提示字符就是 >

具體執行結果以下:

$ ./tinyshell.sh
tinyshell> l
tinyshell.sh
tinyshell> d
Unknown input: d
tinyshell> quit
$

在執行時,先打印出 「tinyshell> 」 提示字符串,等待用戶輸入。

這裏輸入 l 字符,腳本會執行 ls 命令。

輸入 quit 字符串,會退出 while 循環,終止執行。

輸入其餘內容則提示 「Unknown input: 」。

在實際工做中,對這個例子進行擴展,就能模擬一個簡易的 shell 效果,能夠輸入自定義的命令簡寫,來執行一長串的命令,很是方便

例如進行 Android 系統開發,常常用到 adb shell 的各類命令,有些命令帶有不少參數,比較難輸入,仿照這個例子,能夠只輸入一個字符、或者幾個字符,而後執行對應的 adb shell 命令,減小不少輸入。

使用 -e 選項在交互式 shell 中獲取到歷史命令

前面提到在 while 循環中不斷執行 read -p 命令,能夠模擬一個簡易的 shell 效果。

實際使用時遇到一個問題,那就是輸入上光標鍵,會打印 ^[[A,輸入下光標鍵,會打印 ^[[B,不能像 bash 那樣經過上下光標鍵顯示執行過的歷史命令。

具體執行結果以下:

$ ./tinyshell.sh
tinyshell> ^[[A^[[B

這裏打印的 ^[[A 是輸入上光標鍵所顯示,^[[B 是輸入下光標鍵所顯示。

若是想要在執行 read 命令時,能夠經過上下光標鍵來顯示歷史命令,須要加上 -e 選項,且在交互式 shell 中運行。

查看 help read 對 -e 選項說明以下:

-e
use Readline to obtain the line in an interactive shell

即,在交互式 shell 中,read -e 會使用 readline 庫來獲取輸入。
readline 庫支持不少強大的功能,上下光標鍵可以顯示歷史命令,就是由於默認把上下光標鍵綁定到 readline 庫獲取上下歷史命令的函數。
能夠執行下面的命令來進行確認:

$ bind -p | grep -E "previous\-history|next\-history"
"\C-n": next-history
"\eOB": next-history
"\e[B": next-history
"\C-p": previous-history
"\eOA": previous-history
"\e[A": previous-history

這裏的 "e[A" 就是對應上光標鍵,綁定到 previous-history 功能,也就是顯示上一個歷史命令。
"e[B" 對應下光標鍵,綁定到 next_history 功能,也就是顯示下一個歷史命令。

上面的 "C-p" 對應 CTRL-p,也就是同時按下 CTRL 鍵和 p 鍵,能夠看到它也對應上一個歷史命令。
"C-n" 對應 CTRL-n,對應下一個歷史命令。

通常來講,直接在 bash shell 中執行 read 命令,就處於交互式 shell(interactive shell)之下。
具體舉例說明以下:

$ read
^[[A^[[B
$ read -e
read -e

這個例子先是直接執行 read 命令,而後輸入上光標鍵,會打印 ^[[A
而後輸入下光標鍵,又打印 ^[[B

以後,執行 read -e 命令,輸入上光標鍵,會自動填充上一個歷史命令,也就是正在執行的 「read -e」 命令。

注意:這個 -e 選項只在交互式 shell 中才會生效。通常來講,shell 腳本是在非交互式 shell 中執行。
當在 shell 腳本中使用 read -e 時,輸入上下光標鍵,不會再打印 ^[[A^[[B,也不會顯示歷史命令,而是什麼都沒有打印。

這跟 read -p 的效果有所不一樣,read -p 能夠在輸入上下光標鍵時,打印出 ^[[A^[[B

讓 shell 腳本運行在交互模式下

咱們可使用下面幾個方法來讓 shell 腳本在交互模式下執行。

經過 bash -i 選項指定運行在交互模式下

在 bash 中,可使用 bash 的 -i 選項來讓 shell 腳本在交互模式下運行。

查看 man bash 對 -i 選項說明以下:

-i
If the -i option is present, the shell is interactive.

即,在 shell 腳本開頭,把腳本的解釋器寫爲 #/bin/bash -i,執行這個 shell 腳本時,就會運行在交互模式下。

把前面的 tinyshell.sh 腳本修改爲下面的內容來進行驗證:

#!/bin/bash -i

while read -ep "tinyshell> " input; do
    if [ "$input" == "l" ]; then
        ls
    elif [ "$input" == "quit" ]; then
        break
    else
        echo "Unknown input: $input"
   fi
done

相比於以前的腳本,此次的改動點是:

  • 把以前的 #!/bin/bash 改爲 #!/bin/bash -i,添加 -i 選項指定運行在交互模式下。
  • read -p 改爲 read -ep,添加 -e 選項指定在交互模式下用 readline 庫讀取用戶輸入。

執行修改後的腳本,結果以下:

$ ./tinyshell.sh
tinyshell> #!/bin/bash -i
Unknown input: #!/bin/bash -i
tinyshell>

上面的在 「tinyshell>」 以後顯示的 「#!/bin/bash -i」 是輸入兩次上光標鍵後顯示出來的歷史命令。
第一個輸入光標鍵會顯示腳本里面的整個 while 循環語句。

注意:這個腳本在 Linux Debian 系統、 Linux Ubuntu 系統本地測試都能生效,能夠經過上下光標鍵顯示出歷史命令。
可是在 Windows 下經過 ssh 遠程登陸到 Ubuntu 系統,在遠程 Ununtu 系統下執行這個腳本不生效,即便把腳本開頭的解釋器寫爲 #!/bin/bash -iread -e 命令也沒法經過上下光標鍵讀取到歷史命令,輸入上下光標鍵,什麼都沒有打印出來。
在 Mac OSX 系統下測試也不生效。
這幾種狀況都是在 login shell 下運行,查看 readline 庫的配置文件也沒有看到異常,目前緣由不明。
能夠改爲用 source 命令執行腳原本避免這個異常。具體如後面說明所示。

經過 source 命令執行 shell 腳本

經過 bash 的 source 內置命令執行 shell 腳本時,這個腳本運行在當前 bash shell 下,而不是啓動一個子 shell 來執行腳本。

因爲當前 bash shell 是交互式,運行在該 bash shell 下的腳本也是交互式。

此時,腳本開頭的解釋器不須要加 -i 選項,但 read 命令仍是要加 -e 選項來指定用 readline 庫讀取輸入。

修改 tinyshell.sh 腳本內容以下:

#!/bin/bash

while read -ep "tinyshell> " input; do
    if [ "$input" == "l" ]; then
        ls
    elif [ "$input" == "quit" ]; then
        break
    else
        bash -c "${input}"
    fi
done

這個腳本的改動點是:

  • 腳本開頭的解釋器寫爲 #!/bin/bash,不須要加 -i 選項。
  • read 命令加了 -e 選項。
  • 對於不識別的輸入,使用 bash -c 來執行所輸入的內容,這樣就能夠執行外部的命令。

使用 source 命令執行這個腳本的結果以下:

$ source tinyshell.sh
tinyshell> l
tinyshell.sh
tinyshell> echo "This is a tinyshell."
This is a tinyshell.
tinyshell> source tinyshell.sh
tinyshell> quit
tinyshell> quit
$

在執行的時候,先是手動輸入 l 字符,該腳本會相應執行 ls 命令。

而後手動輸入 echo "This is a tinyshell.",該腳本使用 bash -c 來執行這個命令,打印出 This is a tinyshell.

接着輸入上光標鍵,出現上一個歷史命令,顯示當前正在執行的 source tinyshell.sh 命令。
回車以後會再次執行這個腳本。
能夠看到,須要手動輸入兩次 quit,才退出這兩次執行。

上面提到,在 Windows 下經過 ssh 遠程登陸到 Ubuntu 系統,在遠程 Ununtu 系統下,使用 bash 的 -i 選項來執行腳本,read -e 也不能經過上下光標鍵來獲取歷史命令。
此時,經過 source 命令執行腳本,read -e 命令能經過上下光標鍵來獲取歷史命令。

即,經過 bash 的 -i 選項來執行腳本,可能會受到子 shell 環境配置的影響,致使 read -e 命令不能經過上下光標鍵來獲取歷史。

而經過 source 命令來執行腳本,直接運行在當前 bash shell 下,能夠避免子 shell 環境配置的影響,兼容性較強。

注意:經過 source 命令執行腳本時,腳本內不能執行 exit 命令,不然不但會退出腳本執行,還會退出所在的 bash shell。

把腳本自身執行的命令添加到當前歷史記錄

在前面的腳本代碼中,不管是經過 bash 的 -i 選項來執行腳本,仍是經過 source 命令來執行腳本,這兩種方式有一個共同的問題:雖然可使用上下光標鍵查找歷史命令,但找不到腳本自身所執行的命令。

例如輸入 l 字符,tinyshell.sh 腳本執行了 ls 命令。
經過上光標鍵仍是隻能查找到執行腳本以前的歷史命令,查找不到輸入的 l 字符,也找不到腳本所執行的 ls 命令,就像是這個腳本的命令沒有加入到歷史記錄。

若是想在執行腳本時,可使用上下光標鍵查找到腳本自身執行的命令,可使用 history -s 命令。
在上面 while 循環的末尾添加下面的語句,新增的代碼前面用 + 來標識:

else
        bash -c "${input}"
    fi
+   history -s "${input}"
done

添加 history -s "${input}" 語句後,就能經過上下光標鍵找到 input 變量指定的命令。
例如輸入 l 字符,tinyshell.sh 腳本執行了 ls 命令。
input 變量保存的是 l 字符,可以經過上下光標鍵找到 l 命令,找不到 ls 命令。

查看 man bash 對 history 內置命令的 -s 選項說明以下:

history -s arg [arg ...]
-s: Store the args in the history list as a single entry.

即,history -s 命令把所給的參數添加到當前歷史記錄中。
後續經過上下光標鍵獲取歷史命令,就能夠獲取到新添加的命令。

從文件中逐行讀取命令並執行

既然是模擬一個簡易的 shell 效果,固然要具備執行腳本文件的能力。

咱們能夠經過重定向用 read 命令逐行讀取文件內容,而後執行每一行的命令。
一段示例代碼以下:

while read line; do
    echo $line
done < filename

這段代碼會逐行讀取 fliename 這個文件的內容,讀取到最後一行 (EOF) 就會退出 while 循環。

參考這段代碼,對 tinyshell.sh 腳本修改以下:

#!/bin/bash -i

if [ $# -ne 0 ]; then
    filename="$1"
else
    filename="/dev/stdin"
fi

while read -ep "tinyshell> " input; do
    if [ "$input" == "l" ]; then
        ls
    elif [ "$input" == "quit" ]; then
        break
    else
        bash -c "$input"
    fi
done < "$filename"

這個腳本使用 $# 獲取到傳入腳本的參數個數。
若是參數個數不等於 0,那麼用 $1 獲取到第一個參數值,賦值給 filename 變量。
這個參數值用於指定要執行的腳本文件名。

若是沒有提供任何參數,那麼將 filename 賦值爲 /dev/stdin,對應標準輸入。

注意不能將 filename 賦值爲空字符串,不然重定向會提示文件找不到。
重定向空字符串並不表示獲取標準輸入。

爲了不所給文件名帶有空格致使異常,要用雙引號把 $filename 括起來。

這裏採用 bash 的 -i 選項來執行該腳本,因此要在 Linux 本地系統進行測試。
若是想要用 source 命令來執行,須要作一些修改,包括調整 $#$1 的使用。
這裏再也不提供使用 source 命令來執行的例子。

執行修改後的腳本,結果以下:

$ ./tinyshell.sh
tinyshell> l
shfile  tinyshell.sh
tinyshell> quit
$ cat shfile
l
echo "This is in a test file."
whoami
$ ./tinyshell.sh shfile
shfile  tinyshell.sh
This is in a test file.
shy

這個例子先執行 ./tinyshell.sh 命令,不帶參數時,腳本指定從 /dev/stdin 獲取輸入,能夠正常獲取到標準輸入。

輸入的是 l 字符,腳本執行 ls 命令,列出當前目錄下的文件,能夠看到有一個 shfile 文件。

這個 shfile 文件就是要被執行的腳本文件,用 cat shfile 命令列出它的內容,只有三行,每一行都是要執行的命令。

而後執行 ./tinyshell.sh shfile 命令,從打印結果來看,確實逐行讀取到 shfile 文件的內容,並執行每一行的命令。

Bash 的 whoami 命令會打印當前登陸的用戶名,這裏打印出來是 shy

即,使用修改後的 ./tinyshell.sh 來模擬 shell 效果,具備執行腳本文件的能力。
雖然功能還很弱,但基本框架已經搭好,後續能夠根據實際需求進行擴展完善。

注意:使用上面的 「while read」 循環來逐行讀取文件內容,有一個隱晦的異常:若是所給文件的最後一行不是以換行符結尾時,那麼這個 「while read」 循環會處理不到最後一行。具體緣由說明以下。

若是文件的最後一行以換行符結尾,那麼 read 命令遇到換行符,會暫停獲取輸入,並把以前讀取到的內容賦值給指定的變量,命令自身的返回值是 0。
以後 while 命令對這個值進行評估,0 對應 true,執行循環裏面的語句,處理最後一行的內容。

而後再次執行 read 命令,遇到文件結尾 (EOF),read 命令返回非 0 值,對應 false,退出 while 循環。這是正常的流程。

若是文件的最後一行不是以換行符結尾,read 讀取完這一行內容,遇到了 EOF,會把讀取到的內容賦值給指定的變量,命令自身返回值是非 0 值(使用 $? 獲取這個返回值,遇到 EOF 應該是返回 1)。
以後 while 命令對這個非 0 值進行評估,就會退出 while 循環,沒有執行循環裏面的語句。

即,這種狀況下,雖然 read 命令仍是會把最後一行內容賦值給指定變量,可是退出了 while 循環,沒有執行循環裏面的語句,沒有機會處理這一行的內容。
除非在 while 循環外面再處理一次,但會形成代碼冗餘。

下面修改 shfile 文件的內容,最後一行不以換行符結尾,而後執行 ./tinyshell.sh shfile 命令,結果以下:

$ echo -ne "l\nwhoami" > shfile
$ ./tinyshell.sh shfile
shfile  tinyshell.sh
$ cat shfile
l
whoami$

這裏使用 echo 命令的 -n 選項指定不在行末追加換行符,那麼寫入文件的最後一行不以換行符結尾。

能夠看到,執行 ./tinyshell.sh shfile 命令,只處理了第一行的 l 字符,第二行的 whoami 沒有被執行。

cat shfile 命令查看該文件內容,whoami 跟命令行提示符打印在同一行,確實不以換行符結尾。

爲了不這個問題,能夠在腳本中添加判斷,若是所給文件的最後一行不以換行符結尾,則追加一個換行符到文件末尾

要添加的代碼以下,新增的代碼前面用 + 來標識:

if [ $# -ne 0 ]; then
    filename="$1"
+    if test -n "$(tail "$filename" -c 1)"; then
+        echo >> "$filename"
+    fi
else
    filename="/dev/stdin"
fi

新增的代碼用 tail "$filename" -c 1 命令獲取到 filename 文件的最後一個字符。
"$(tail "$filename" -c 1)" 語句通過命令擴展後返回這個字符。

若是這個字符是換行符,因爲 bash 在擴展後會自動丟棄字符串的最後一個換行符,獲取到的內容爲空,test -n 返回爲 false,不作處理。

若是最後一個字符不是換行符,那麼內容不爲空,test -n 返回爲 true,就會執行 echo >> "$filename" 命令追加一個換行符到文件末尾。
echo 不帶參數時,默認輸出一個換行符, >> 表示追加內容到文件末尾。

添加這幾個語句後,再執行 ./tinyshell.sh shfile 命令,就能處理到最後一行的 whoami,以下所示:

$ ./tinyshell.sh shfile
shfile  tinyshell.sh
shy
$ cat shfile
l
whoami
$

能夠看到,執行以後,shfile 文件的最後一行 whoami 後面被追加了一個換行符,輸出該文件內容,命令行提示符會換行打印。

一般來講,在 Windows 下複製內容到新建文件,而後保存這個文件,文件的最後一行可能就不以換行符結尾。

使用 -s 選項指定不回顯用戶輸入

在 bash 下,輸入密碼時,通常不會回顯用戶輸入,而是什麼都不顯示。
咱們可使用 read 命令的 -s 選項模擬這個效果。

查看 help read 對 -s 選項的說明以下:

-s
do not echo input coming from a terminal

具體舉例以下:

$ read -s -p "Your input will not echo: " input
Your input will not echo: $ echo $input
sure?

這個例子指定了 -s 選項,不回顯輸入內容到終端。
-p 指定了提示字符串,輸入內容會被保存到 input 變量。
在輸入的時候,界面上不會顯示任何字符。

回車以後,命令行提示符直接顯示在同一行,因爲沒有回顯換行符,因此沒有換行。

打印 input 變量的值,能夠看到手動輸入的內容是 「sure?」。

若是須要在模擬的簡易 shell 中輸入密碼,能夠添加相似下面的代碼,讓輸入密碼時不回顯,新增的代碼前面用 + 來標識:

elif [ "$input" == "quit" ]; then
        break
+    elif [ "$input" == "root" ]; then
+        read -s -p "Please input your password: " pwd
+        # handle password with $pwd
+        echo
+        echo "Your are root now."
    else
        bash -c "${input}"
    fi

這裏添加了對 root 字符串的處理,先執行 read -s -p "Please input your password: " pwd 命令,提示讓用戶輸入密碼。
輸入的內容不會回顯,會保存在 pwd 變量中,能夠根據實際須要進行處理。

新增的第一個 echo 命令用於從 "Please input your password: " 字符串後面換行,不然會直接輸出到同一行上。

第二個 echo 命令只是打印一個提示語,能夠根據實際需求改爲對應的提示。

使用 -n 選項指定讀取多少個字符

執行 read 命令讀取標準輸入,會不停讀取輸入內容,直到遇到換行符爲止。

若是咱們預期最多隻讀取幾個字符,可使用 -n 選項來指定。

查看 help read 對 -n 選項說明以下:

-n nchars
return after reading NCHARS characters rather than waiting for a newline, but honor a delimiter if fewer than NCHARS characters are read before the delimiter

即,read -n nchars 指定最多隻讀取 nchars 個字符。
輸入 nchars 個字符後,即便尚未遇到換行符,read 也會中止讀取輸入,返回讀取到的內容。

若是在輸入 nchar 個字符以前,就遇到換行符,也會中止讀取輸入。

使用 -n 選項並不表示必定要讀取到 nchars 個字符,另一個 -N 選項表示必定要讀取到 nchars 個字符,
這裏對 -N 選項不作說明。

下面會在模擬的簡易 shell 中實現一個小遊戲,增長一點趣味性。
這個小遊戲使用 read -n 1 來指定每次只讀取一個字符,以便輸入字符就馬上中止讀取,不須要再按回車。

具體實現代碼以下,這也是 tinyshell.sh 腳本最終版的代碼:

#!/bin/bash -i

if [ $# -ne 0 ]; then
    filename="$1"
    if test -n "$(tail "$filename" -c 1)"; then
        echo >> "$filename"
    fi
else
    filename="/dev/stdin"
fi

function game()
{
    local count=0
    local T="T->"

    echo -e "NOW, ATTACK! $T"
    while read -s -n 1 char; do
        case $char in
            "h") ((--count)) ;;
            "l") ((++count)) ;;
            "q") break ;;
        esac

        for ((i = 0; i < count; ++i)); do
            echo -n "    "
        done
        echo -ne "$T      \r"
    done
    echo
}

while read -ep "tinyshell> " input; do
    if [ "$input" == "l" ]; then
        ls
    elif [ "$input" == "quit" ]; then
        break
    elif [ "$input" == "root" ]; then
        read -s -p "Please input your password: " pwd
        # handle with $pwd
        echo
        echo "Your are root now."
    elif [ "$input" == "game" ]; then
        game
    else
        bash -c "${input}"
    fi
    history -s "${input}"
done < "$filename"

主要改動是增長對 game 字符串的處理,輸入這個字符串,會執行自定義的 game 函數。
該函數打印 T-> 字符串,像是一把劍(也許吧),而後用 read -s -n 1 char 命令指定每次只讀取一個字符,且不回顯。

若是輸入 l 字符,則把 T-> 字符串的顯示位置往右移。
輸入 h 字符,則把 T-> 字符串的顯示位置往左移。
看起來是一個左右移動的效果。
輸入 q 字符,退出該遊戲。

具體執行結果以下:

$ ./tinyshell.sh
tinyshell> game
NOW, ATTACK! T->
        T->
tinyshell>

因爲沒有回顯輸入字符,且始終在同一行顯示 T-> 字符串,因此這個打印結果體現不出 T-> 字符串的移動。
能夠實際執行這個腳本,屢次輸入 lh 字符,就能看到具體效果。
最後輸入 q 字符退出遊戲。

總結

至此,咱們已經使用 read 命令來獲取用戶輸入,模擬了一個簡易的 shell 效果。
這個簡易的 shell 能夠執行腳本文件,能夠經過上下光標鍵獲取到 bash 的歷史命令,支持輸入密碼不回顯,還實現了一個小遊戲。

總結 read 命令的使用關鍵點以下:

  • 使用 -p 選項來打印提示字符,模擬 shell 的命令行提示符
  • 使用 -e 選項在交互式 shell 中用 readline 庫讀取輸入,能夠避免輸入上下光標鍵顯示亂碼
  • 使用 -s 選項指定不回顯輸入內容,可用於輸入密碼、輸入遊戲控制按鍵等狀況
  • 使用 -n 1 選項指定只讀取一個字符,輸入字符馬上結束讀取,能夠在遊戲中快速響應按鍵,不用按下回車才能響應
  • 使用 「while read」 循環來重定向讀取文件,能夠逐行讀取文件內容,執行相應命令,就像是執行腳本文件
相關文章
相關標籤/搜索