Shell 獲得用戶輸入

在 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í)例詳解

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容