在 Bash 下我們可以通過其內(nèi)部命令 read 接收用戶來自鍵盤的輸入,并可以將輸入的內(nèi)容賦值給一個(gè)變量。
實(shí)例:基本的讀取
read 命令比較常用的語法格式如下所示:
read [-p prompt] [variable1 variable2...]
-p 選項(xiàng)用于在嘗試讀取任何輸入之前,顯示 prompt(提示信息)的內(nèi)容到標(biāo)準(zhǔn)錯(cuò)誤輸出。我們一般使用這一選項(xiàng)來指定提示用戶輸入哪些內(nèi)容的信息。read 命令會(huì)每次從標(biāo)準(zhǔn)輸入(或使用 -u 選項(xiàng)指定的文件描述符中)讀取一行的內(nèi)容,它會(huì)將第一個(gè)單詞賦值給第一個(gè)變量 variable1,第二個(gè)單詞賦值給第二個(gè)變量 variable2,依次類推。如果輸入的單詞數(shù)少于指定的變量數(shù),那么剩下的 name 變量的值會(huì)被設(shè)為空,環(huán)境變量 IFS 中的字符被作為分隔符來將輸入的內(nèi)容分隔為單詞。
下面是一個(gè)簡單的使用示例:
#! /bin/bash
read -p "Enter your name, please: " username
read -p "Enter your email, please: " email
read -p "Are you sure to continue? [y/n] " input
case $input in
[yY]*)
echo "Your name is $username"
echo "Your email is $email"
;;
[nN]*)
exit
;;
*)
echo "Just enter y or n, please."
exit
;;
esac
使用效果:

實(shí)例:輸入超時(shí)
我們可以使用 read 命令的 -t 選項(xiàng)來設(shè)置 read 命令讀取用戶輸入時(shí)的超時(shí)時(shí)間。如果在指定的秒數(shù)內(nèi)沒有讀入一整行的輸入(即沒有輸入回車鍵),read 命令就會(huì)超時(shí)并返回失敗。我們可以在上一小節(jié)的實(shí)例腳本腳本中加入讀取輸入超時(shí)功能,修改之后的腳本的內(nèi)容如下:
#! /bin/bash
read -t 5 -p "Enter your name, please: " username
read -t 5 -p "Enter your email, please: " email
read -t 5 -p "Are you sure to continue? [y/n] " input
case $input in
[yY]*)
echo "Your name is $username"
echo "Your email is $email"
;;
[nN]*)
exit
;;
*)
echo "Just enter y or n, please."
exit
;;
esac
使用效果:

實(shí)例:隱藏方式讀取
我們可以使用 read 命令的 -s 選項(xiàng)來隱藏用戶的輸入。如果指定了 -s 選項(xiàng),則來自終端的輸入不會(huì)被顯示出來。這對(duì)我們的腳本在需要對(duì)用戶輸入的密碼進(jìn)行驗(yàn)證時(shí)(為了安全)是很有用的。
下面是一個(gè)簡單的使用示例:
#! /bin/bash
password=''
echo -n "Enter password: "
# 使用 while 循環(huán)隱式地從標(biāo)準(zhǔn)輸入每次讀取一個(gè)字符,且反斜杠不做轉(zhuǎn)義字符處理
# 然后將讀取的字符賦值給變量 char
while IFS= read -r -s -n1 char
do
# 如果讀入的字符為空,則退出 while 循環(huán)
if [ -z $char ]
then
echo
break
fi
# 如果輸入的是退格或刪除鍵,則移除一個(gè)字符
if [[ $char == $'\x08' || $char == $'\x7f' ]]
then
[[ -n $password ]] && password=${password:0:${#password}-1}
printf '\b \b'
else
password+=$char
printf '*'
fi
done
echo "Password is: $password"
使用效果:

實(shí)例:從文件中讀取
使用 read 命令從文件中讀取數(shù)據(jù)的方法主要有兩種,一種是在 while 循環(huán)或 until 循環(huán)中使用 read 命令,通過文件描述符一行一行地讀取文件的內(nèi)容;另一種就是本節(jié)我們要介紹的方法 —— 在 for 循環(huán)中使用命令 “cat <filename>” 來讀取文件中的內(nèi)容。
在 for 循環(huán)中使用命令 “cat <filename>” 來讀取文件的語法是:
for data in $(cat filename)
do
command1
command2
...
commandN
done
上述語法中 filename 代表一個(gè)文本文件,讀取的內(nèi)容會(huì)被存入變量 data,此變量可以在 for 循環(huán)體中使用,用于對(duì)讀入的數(shù)據(jù)進(jìn)行處理 。
使用上述方法需要注意:它是逐個(gè)單詞地讀取文件內(nèi)容。因?yàn)槭褂眠@種方法讀取文件內(nèi)容時(shí),它使用環(huán)境變量 IFS 的值作為分隔符,由于 $IFS 的默認(rèn)值是 “<space><tab><newline>”,所以它會(huì)首先以空格作為分隔符,來讀取文件的內(nèi)容。因此,如果我們想要使用這種方法逐行地讀取文件的內(nèi)容,就需要在調(diào)用 for 循環(huán)之前先修改 $IFS 的值。當(dāng)然,如果我們能確定文件的內(nèi)是每行只有一個(gè)單詞,就無需進(jìn)行修改。
#! /bin/bash
old_IFS=$IFS
# 參數(shù)個(gè)數(shù)不為 1
if [ $# -ne 1 ]
then
echo "Usage: `basename $0` filename"
exit
fi
# 如果指定的文件不存在
if [ ! -f $1 ]
echo "The file $1 doesn't exist!"
exit 1
fi
# 修改環(huán)境變量 IFS 的值,使下面的 for 循環(huán)以換行符作為分隔符
IFS=$'\n'
for line in $(cat $1)
do
echo $line
done
IFS=$old_IFS
使用效果:

盡管使用 while 循環(huán)讀取文件的內(nèi)容相對(duì)比較方便,但是它也有副作用,它讀取的每行內(nèi)容會(huì)去掉重復(fù)的空格和制表符,即會(huì)消除每行的原有格式。而將 for 循環(huán)結(jié)合環(huán)境變量 $IFS 使用可以保留每行原有的格式。所有,我們可以根據(jù)不同的需求來選擇使用 while 還是 for 循環(huán)來讀取文件的內(nèi)容。
本文參考自 《Linux Shell命令行及腳本編程實(shí)例詳解 》