shell程式設計之處理使用者輸入
目錄
前言
>>>目前為止,我們涉及到的知識包括如何編寫指令碼,處理資料、變數和檔案
>>>bash shell提供了不同方法來從使用者獲取資料,包括命令列引數,命令列選項,以及從鍵盤讀取輸入等
①命令列引數
讀取引數
>>>bash shell會將一些稱為位置引數(positional parameter)的特殊變數分配給輸入到命令列中的所有引數
>>>當需要輸入多個命令列引數,需要在命令列上每個引數用空格隔開
案例
[[email protected] test]$ cat parameter.sh
#!/bin/bash
echo "file_name=$0"
echo "parameter1=$1"
echo "parameter2=$2"
[[email protected] test]$ bash parameter.sh para_1 para_2
file_name=parameter.sh
parameter1=para_1
parameter2=para_2
說明
>>>位置引數變數是標準的數字,$0是程式名parameter.sh,$1是第一個引數para_1,$2是第二個引數para_2
>>>變數在第9個之後變數最好用大括號括起來 ${10}
>>>如果引數含有空格,則需要將引數用引號引起來,否則會當做兩個變數使用
測試引數
>>>在shell指令碼使用命令列引數時,如果指令碼沒有加引數可能會出問題,為了避免此情況, 在使用引數前,可以先用test命令測試引數是否存在
案例
[[email protected] test]$ cat parameter.sh
#!/bin/bash
if [ -z "$1" ] #使用test命令"-z"測試$1字串是否為0
then
echo "usage:bash $0 para_1" #$1字串為0的話的話,提示使用者該以什麼格式輸入,並退出
exit
else
echo "Great,parameter1=$1"
fi
[ [email protected] test]$ bash parameter.sh
usage:bash parameter.sh para_1
[[email protected] test]$ bash parameter.sh hello
Great,parameter1=hello
②特殊變數——記錄命令列引數
獲取位置引數的個數:使用特殊變數$#,
可以在指令碼任何地方使用這個變數,即用法用普通變數
案例
[[email protected] test]$ cat parameter.sh
#!/bin/bash
echo "count of parameter : $# "
[[email protected] test]$ bash parameter.sh
count of parameter : 0
[[email protected] test]$ bash parameter.sh 1 2 3
count of parameter : 3
案例:在使用引數前測試引數的總數,並測試引數是否為空
[[email protected] test]$ cat parameter.sh
#!/bin/bash
if [ $# -ne 2 ]
then
echo "Usage:bash $0 parameter1 parameter2"
else
if [ -z $1 ] || [ -z $2 ]
then
echo "error:check the parameter"
else
echo "Graet parameter1=$1,parameter2=$2"
fi
fi
[[email protected] test]$ bash parameter.sh
Usage:bash parameter.sh parameter1 parameter2
[[email protected] test]$ bash parameter.sh hello ""
error:check the parameter
[[email protected] test]$ bash parameter.sh hello world
Graet parameter1=hello,parameter2=world
命令列最後一個引數: ${!#}
[[email protected] test]$ cat parameter.sh
#!/bin/bash
echo "the last parameter is ${!#}"
[[email protected] test]$ bash parameter.sh 1 2 3
the last parameter is 3
抓取引數
>>>需求:將命令列引數全部抓取下來,然後再去遍歷
>>>思路:bash shell提供了連個變數$*和[email protected]區隊所有引數快速訪問
說明:
>>>$*是將命令列上提供的所有引數當做單個單詞儲存,即將所有引數當做一個整體的變數
>>>$@是將命令上提供的所有引數當做一個個獨立的引數,即當做一個列表,會單獨處理每個引數
案例
[[email protected] test]$ cat parameter.sh
#!/bin/bash
#testing $* and [email protected]
echo "Using the \$* method: $*"
echo "Using the \[email protected] method: [email protected]"
[[email protected] test]$ bash parameter.sh hello world
Using the $* method: hello world
Using the [email protected] method: hello world
從表面上看,兩個變數產生的輸出是一樣的,都顯示了所有命令列引數
下面的案例給出二者的差異
案例
[[email protected] test]$ cat parameter.sh
#!/bin/bash
count=1
for i in "$*"
do
echo "\$* parameter #$count : $i"
count=$[ $count + 1 ]
done
count=1
for j in "[email protected]"
do
echo "\[email protected] parameter $count : $j"
count=$[ $count + 1 ]
done
[[email protected] test]$ bash parameter.sh hello world
$* parameter 1 : hello world
[email protected] parameter 1 : hello
[email protected] parameter 2 : world
注意:[email protected]和$*最好用引號引起來,否則輸出會有差異
③移動變數
>>>bash shell提供了shift命令來操作命令列引數,根據它們的相對位置來移動命令列引數
>>>此方法在你不知道有多少引數是個不錯的選擇,你可以只操作第一個引數,移動引數,然後繼續操作第一個引數
案例
[[email protected] test]$ cat shift.sh
#!/bin/bash
count=1
while [ -n "$1" ]
do
echo "parameter $count: $1"
count=$[ $count + 1 ]
shift
done
[[email protected] test]$ bash shift.sh a b c d
parameter 1: a
parameter 2: b
parameter 3: c
parameter 4: d
>>> shift預設步長為1,引數左移1位,若為shift 2,步長為2
案例
[[email protected] test]$ cat shift.sh
#!/bin/bash
count=1
while [ -n "$1" ]
do
echo "parameter $count: $1"
count=$[ $count + 1 ]
shift 2
done
[[email protected] test]$ bash shift.sh 1 2 3 4 5 6 7 8
parameter 1: 1
parameter 2: 3
parameter 3: 5
parameter 4: 7
注意:執行此指令碼不能傳入奇數個命令列引數,否則會造成死迴圈
>>>使用shift命令的時候要小心,如果引數被移除了,這些值就會被丟棄了,無法再恢復
[[email protected] test]$ cat shift.sh
#!/bin/bash
count=1
while [ -n "$1" ]
do
echo "parameter $count: $1"
count=$[$count+1]
shift
done
echo""
echo "$*"
[[email protected] test]$ bash shift.sh a b c d
parameter 1: a
parameter 2: b
parameter 3: c
parameter 4: d
說明:當我執行完shift命令後,再去echo命令列引數,輸出為空,即原來的引數被丟棄了
④處理選項
>>>bash命令後面的選項是在單破折號後的字母,他能改變命令的行為
>>>處理簡單選項可以使用while迴圈和case語句
處理簡單選項
案例
[[email protected] test]$ cat option.sh
#!/bin/bash
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the option -a";;
-b) echo "Found the option -b";;
-c) echo "Found the option -c";;
*) echo "$1 is not an option";;
esac
shift
done
[[email protected] test]$ bash option.sh -a -b -c -d
Found the option -a
Found the option -b
Found the option -c
-d is not an option
分離引數和選項
>>>在執行指令碼的時候,同時用到選項和引數的情況下,如何將二者分開
>>>使用特殊字元雙破折號(--)即shell會用雙破折號表明選項列表結束, 在雙破折號之後,指令碼就可以將剩下的命令列引數當引數處理
案例
[[email protected] test]$ cat option.sh
#!/bin/bash
while [ -n "$1" ]
do
case "$1" in
-a) echo "Found the option -a";;
-b) echo "Found the option -b";;
-c) echo "Found the option -c";;
--) shift
break;;
*) echo "$1 is not an option"
esac
shift
done
count=1
for i in "[email protected]"
do
echo "parameter $count = $i"
count=$[ $count + 1 ]
done
[[email protected] test]$ bash option.sh -a -b -c -- hello world
Found the option -a
Found the option -b
Found the option -c
parameter 1 = hello
parameter 2 = world
說明:break命令之前的shift命令,是用來移除雙破折號,避免出現在引數中
⑤獲得使用者輸入——read命令
>>>當需要在指令碼執行時,實現人與指令碼的互動,即為實時獲得使用者的輸入, 比如寫一個用來獲得使用者實時輸入的密碼的指令碼 bash shell提供了一個命令:read命令,解決了我們的需求
基本的讀取
>>>read命令從標準輸入(鍵盤)或另一個檔案描述符中接受輸入,在收到輸入後,raad命令會將資料放進一個變數
案例:
[[email protected] test]$ cat read.sh
#!/bin/bash
echo -n "Please input your username:"
read username
echo "-----------"
echo "Welcome,$username!"
[[email protected] test]$ bash read.sh
Please input your username:bei
-----------
Welcome,bei!
注意:倒數第三行的"bei"是我自己在鍵盤上敲的,即標準輸入,然後放進變數username,在指令碼後面使用
echo的-n選項把文字字串和命令輸出顯示在同一行,即該選項不會在字串末尾輸出換行符
案例:使用-p選項,直接在read命令列指定提示符
[[email protected] test]$ cat read.sh
#!/bin/bash
read -p "Please input your username: " username
echo "-----------"
echo "Welcome,$username"
[[email protected] test]$ bash read.sh
Please input your username: bei
-----------
Welcome,bei
超時
>>>指令碼啟動後,執行read命令時,若使用者遲遲未輸入,指令碼會一直苦等著
>>>如果想讓使用者是否有輸入,指令碼都會繼續往下執行,可以使用-t選項來制定一個定時器
>>>當計時器到期後,read命令會返回一個非零退出狀態碼
案例
[[email protected] test]$ cat read.sh
#!/bin/bash
if read -t 5 -p "Please input your username: " username
then
echo "Welcome,$username"
else
echo "Sorry,you are too late to input your username."
fi
[[email protected] test]$ bash read.sh
Please input your username: Sorry,you are too late to input your username.
[[email protected] test]$ bash read.sh
Please input your username: bei
Welcome,bei
隱藏方式讀取
>>>需求:當希望在螢幕輸入的內容,不想被“顯示”在螢幕上,比如在輸入密碼的時候
>>>方法:使用-s選項,該選項會避免將傳給read命令的資料顯示在顯示器上
(實際上,資料會被顯示,只是read命令會將文字顏色設成跟背景色一樣)
案例
[[email protected] test]$ cat read.sh
#!/bin/bash
read -t 5 -p "Please input your username: " username
read -t 5 -s -p "Please input your password: " password
echo ""
echo "Welcome,$username,your password is $password"
[[email protected] test]$ bash read.sh
Please input your username: bei
Please input your password:
Welcome,bei,your password is hahahaha
從檔案中讀取
>>>使用read命令讀取Linux系統上檔案裡儲存的資料,每次呼叫read命令,都會從檔案中讀取一行文字
>>>當檔案中再沒有內容時,read命令會退出並返回非零退出狀態碼
>>>read命令從檔案讀取輸入——cat $file | while read line
案例
[[email protected] test]$ cat date
IP1 1.1.1.1
IP2 192.168.1.1
IP6 2.2.2.2
IP9 172.16.1.1
[[email protected] test]$ cat read.sh
#!/bin/bash
count=1
read -p "Input the file you want to read:" file
cat $file | while read line
do
echo "line $count : $line"
count=$[ $count + 1 ]
done
echo "Finished processing the file $file"
[[email protected] test]$ bash read.sh
Input the file you want to read:./date
line 1 : IP1 1.1.1.1
line 2 : IP2 192.168.1.1
line 3 : IP6 2.2.2.2
line 4 : IP9 172.16.1.1
Finished processing the file ./date
說明:
>>>cat命令的輸出內容通過管道符傳遞作為read的輸入內容
>>>當檔案讀取完最後一行,read命令返回一個非零狀態碼,while迴圈結束
說明:
>>>以上內容是本人學習的總結
>>>如還有錯誤,請留言,指正
>>>亦可分享自己的想法,互相學習