shell程式設計其實真的很簡單(五)
通過前幾篇文章的學習,我們學會了shell的基本語法。在linux的實際操作中,我們經常看到命令會有很多引數,例如:ls -al 等等,那麼這個引數是怎麼處理的呢? 接下來我們就來看看shell指令碼對於使用者輸入引數的處理。 命令列引數處理 根據引數位置獲取引數
bash shell可根據引數位置獲取引數。通過 $1 到 $9 獲取第1到第9個的命令列引數。{}來獲取了, 例如獲取第10個引數,那麼可以寫為${10}。
示例一:
#!/bin/bash #testinput.sh echo "file name: $0" echo "base file name: $(basename $0)" echo "param1: $1" echo "param2: ${2}"
執行上面的的shell
./testinput.sh 12 34
最終得到的結果如下:
file name: ./testinput4.sh
param1: 12
param2: 34
成功的得到檔名和命令列輸入的引數(命令列引數以空格分隔,如果引數包含了空格,那麼久必須新增引號了)
(basename $0)。
試想一下,假如我們寫的shell的這個引數很多,那如果像上面那樣一個一個去獲取引數,那豈不是要寫瘋!下面就來看看如何解決這種情況。
讀取所有引數
方法一
既然bash shell通過位置可獲取引數,那意味著如果我們知道引數的總個數就可以通過迴圈依次獲取引數。那麼如何獲取引數總個數呢?
在bash shell中通過 $# 可獲取引數總數。
示例:(迴圈獲取引數)
#!/bin/bash for (( index=0; index <= $#; index++ )) do echo ${!index} done
以上示例,我們通過 $# 獲取總引數個數。然後通過迴圈獲取每個位置的引數。注意: 按照正常的理解,上面的 ${!index} 應該是 KaTeX parse error: Expected '}', got 'EOF' at end of input: {index}才對, 對吧? 但是,由於符號,bash shell在這個地方是用了!符號,所以以上才寫為了${!index}。
方法二
在bash shell中還可以通過 $* 和 [email protected] 來獲取所有引數。但是這兩者之間有著很大的區別:
$* 會將命令列上提供的所有引數當作一個單詞儲存, 我們得到的值也就相當於是個字串整體。
[email protected] 會將命令列上提供的所有引數當作同一字串中的多個獨立的單詞。
可能文字看起來描述的不太清楚,那麼還是通過示例來看二者的區別吧:
#!/bin/bash
#testinput.sh
var1=$*
[email protected]
echo "var1: $var1"
echo "var2: $var2"
countvar1=1
countvar2=1
for param in "$*"
do
echo "first loop param$countvar1: $param"
countvar1=$[ $countvar1 + 1 ]
done
echo "countvar1: $countvar1"
for param in "[email protected]"
do
echo "second param$countvar2: $param"
countvar2=$[ $countvar2 + 1 ]
done
echo "countvar2: $countvar2"
執行上面的示例:
./testinput.sh 12 34 56 78
上面示例的輸出結果為:
var1: 12 34 56 78
var2: 12 34 56 78
param1: 12 34 56 78
countvar1: 2
param1: 12
param2: 34
param3: 56
param4: 78
countvar2: 5
通過上面的結果可見,直接輸出看起來二者結果一樣,但是通過for迴圈就可看出二者的區別了。上一篇文章我們講到for迴圈會通過IFS定義的值進行分割,因此預設情況下,如果我們上面在for迴圈處不加引號,那麼根據IFS中所定義的空格分割,最終也會導致看不出二者區別。
獲得使用者輸入
單個輸入
有時候,我們在shell執行過程中獲取使用者的輸入,以此與使用者進行互動。這是通過read命令來實現的。下面就來看看其用法:
示例一:
#!/bin/bash
echo -n "yes or no(y/n)?"
read choice
echo "your choice: $choice"
執行以上示例,首先會輸出”yes or no(y/n)?“, 然後會等待使用者輸入(-n引數表示不換行,因此會在本行等待使用者輸入),當用戶輸入後,會把使用者輸入的值賦值給choice變數, 然後最終輸出 “your choice: (你輸入的內容)”。
事實上,我們可以不指定read後面的變數名,如果我們不指定, read命令會將它收到的任何資料都放進特殊環境變數REPLY中。如下:
示例二:
#!/bin/bash
echo -n "yes or no(y/n)?"
read
echo "your choice: $REPLY"
以上示例與示例一是等價的。
有時候,我們需要使用者輸入多個引數,當然,shell是支援一次接受多個引數輸入的。
多個輸入
示例三:
#!/bin/bash
read -p "what's your name?" first last
echo first: $first
echo last: $last
以上示例首先輸出“what’s your name?”, 然後在本行等待使用者輸入(此處用read -p實現以上示例的echo -n + read命令的不換行效果),輸入的引數以空格分隔,shell會把輸入的值依次賦值給first和last兩個變數。如果輸入的值過多,假如我輸入了3個值,那麼shell會把剩下的值都賦值給最後一個變數(即第二三兩個的值都會賦值給last變數)。
細想一下,有個問題,假如使用者一直不輸入,怎麼辦?一直等待?
超時設定
我們可以通過read -t 來指定超時時間(單位為秒),如果使用者在指定時間內沒輸入,那麼read命令就會返回一個非0的狀態碼。
示例四:
#/bin/bash
if read -t 5 -p "Please enter your name: " name
then
echo "Hello $name"
else
echo "Sorry, timeout! "
fi
執行以上示例,如果超過5秒沒輸入,那麼就會執行else裡面的。
小結
本篇簡單的介紹了shell的輸入引數以及接收使用者輸入。大家可以舉一反三,結合之前所學的基礎知識,可以寫一些小的指令碼應用了。