文章目錄
- 1. 指令行參數
-
- 1.1 讀取參數
- 1.2 讀取腳本名--`$0`
- 1.3 測試參數--`-n`
- 2.特殊參數變量
-
- 2.1 參數統計--`$#`
- 2.2 抓取所有資料--`$*`和`[email protected]`[周遊指令行的絕妙方法]
- 3.移動變量--shift指令[周遊指令行參數的另一個好方法]
- 4.處理選項
-
- 4.1 查找選項
- 4.2 使用getopt指令-格式化指令行選項和參數
- 4.3 使用更進階的getopts--避開getopt指令的劣勢擴充了一些功能
- 5.将選項标準化
- 6.獲得使用者輸入--`read`
-
- 6.1 基本的擷取
- 6.2 逾時--read需要逾時判斷
- 6.3 隐藏方式讀取--`-s`典型應用于密碼輸入上
- 6.4 從檔案讀取
1. 指令行參數
1.1 讀取參數
bash shell會将一些稱為位置參數(positional parameter)的特殊變量配置設定給輸入到指令行中的所有參數(包括shell所執行的腳本名稱)。
位置參數變量是标準的數字:
$0
是程式名,
$1
是第一個參數,通常依次到
$9
。
eg:
a=1
for((num=1;num<$1;num++))
do
a=$[ $a+$num ]
done
echo $a
#11
notice:
- 需要輸入更多的指令行參數,則每個參數都必須用空格分開。
- shell腳本會自動将指令行參數的值配置設定給變量,不需要作任何處理。
- 當遇到傳入參數帶有空格時,記得用引号包括起來(單雙引号都可)。
- 當指令行參數超過9個時候,第10個參數以及第10+n個參數的引用需要使用花括号。如
${10}
1.2 讀取腳本名– $0
$0
以用$0參數擷取shell在指令行啟動的腳本名。
讀取腳本名有如下需要注意的:
- 如果使用另一個指令來運作shell腳本,指令會和腳本名混在一起,出現在$0參數中。
- 當傳給$0變量的實際字元串不僅僅是腳本名,而是完整的腳本路徑時,變量$0就會使用整個路徑。
Q:如何避免上述問題?
A:使用
basename
指令即可。
eg:
echo $0
path=$(basename $0)
echo $path
#/home/hogoadr/workspace/share/george/shell/myshell
#myshell
1.3 測試參數– -n
-n
當腳本認為參數變量中會有資料而實際上并沒有時,腳本很有可能會産生錯誤消息。
在使用參數前一定要檢查其中是否存在資料。
可以使用**-n**測試來檢查指令行參數$1中是否有資料。
eg:
if [ -n "$1" ] #使用 -n 測試 是否執行使用參數1的相關代碼塊
then
a=1
for((num=1;num<$1;num++))
do
a=$[ $a+$num ]
done
echo $a
else
echo "no parameter 1 "
fi
#no parameter 1
2.特殊參數變量
2.1 參數統計– $#
$#
特殊變量$#含有腳本運作時攜帶的指令行參數的個數。可以在腳本中任何地方使用這個特殊變量,就跟普通變量一樣。這樣就可以避免多個參數需要一個一個測試的繁瑣。
eg:
if [ $# -eq 2 ];then
echo "parameter is 2"
elif [ $# -eq 1 ];then
if [ -n "$1" ];then
a=1
for((num=1;num<$1;num++))
do
a=$[ $a+$num ]
done
echo $a
fi
else
echo "no parameter 1 "
fi
#根據攜帶參數走不同分支
notice:
- if-then語句用**-ne**測試指令行參數數量。如果參數數量不對,會顯示一條錯誤消息告知腳本的正确用法。
-
用來擷取指令行中最後一個參數。${!#}
- 當指令行上沒有任何參數時,
的值為0,params變量的值也一樣,但${!#}變量會傳回指令行用到的腳本名。$#
2.2 抓取所有資料– $*
和 [email protected]
[周遊指令行的絕妙方法]
$*
[email protected]
指令 | 描述 | 異 | 同 |
---|---|---|---|
$* | 用來輕松通路所有的參數 | 1.将指令行上提供的所有參數 當作一個單詞儲存 2.基本上$*變量會将這些參數視為一個整體 而不是多個個體 | 能夠在單個變量中存儲所有的指令行參數 |
[email protected] | 用來輕松通路所有的參數 | 将指令行上提供的所有參數當作同一字元串中的多個獨立的單詞,通常使用for指令周遊得到每個參數值 |
eg:
cnt=1
for para in $"$*"
do
echo "\$* $cnt = $para"
cnt=$[ $cnt + 1 ]
done
cnt=1
for para in $"[email protected]"
do
echo "\[email protected] $cnt = $para"
cnt=$[ $cnt + 1 ]
done
#$* 1 = 5:8:6:9:7
#[email protected] 1 = 5
#[email protected] 2 = 8
#[email protected] 3 = 6
#[email protected] 4 = 9
#[email protected] 5 = 7
3.移動變量–shift指令[周遊指令行參數的另一個好方法]
shift指令會根據它們的相對位置來移動指令行參數。(周遊指令行參數的另一個好方法,在不知道有多少個指令行參數的時候,隻讀第一個參數)
notice:
- 在使用shift指令時,預設情況下它會将每個參數變量向左移動一個位置。
- 使用shift指令的時候要小心。如果某個參數被移出,它的值就被丢棄了,無法再恢複。
- 可以一次性移動多個位置,即給shift 指令後面跟個n個位置參數,指明要移動的位置數。
- 通過使用shift指令的參數,可以輕松的跳過不需要的參數。
eg:
echo
count=1
while [ -n "$1" ]
do
echo "Parameter #$count = $1" #不知道實際參數個數,隻取第一個參數
count=$[ $count + 1 ]
shift
done
#Parameter #1 = 5
#Parameter #2 = 8
#Parameter #3 = 6
#Parameter #4 = 9
#Parameter #5 = 7
4.處理選項
4.1 查找選項
bash shell 腳本可以像處理指令行參數一樣處理指令行選項。
處理指令行選項需要注意如下兩點:
- 分離參數和選項;
- 處理帶值的選項。
Q:如何分離參數和選項?
A:Linux使用标準方法是使用特殊字元。雙破折線(–),shell會用雙破折現線來表明選項清單的結束。
ps:處理帶值的選項通常包括注意選項的合并。eg:
ls -la
4.2 使用getopt指令-格式化指令行選項和參數
getopt指令可以接受一系列任意形式的指令行選項和參數,并自動将它們轉換成适當的格式,是一個在處理指令行選項和參數時非常友善的工具。
其格式如下:
getopt optstring parameters
optstring是這個過程的關鍵所在。
它定義了指令行有效的選項字母,還定義了哪些選項字母需要參數值。
其流程如下:
首先,在optstring中列出你要在腳本中用到的每個指令行選項字母。
然後,在每個需要參數值的選項字母後加一個冒号。
getopt指令會基于你定義的optstring解析提供的參數。
eg:
$ getopt ab:cd -a -b test1 -cd test2 test3
-a -b test1 -c -d -- test2 test3
ps: getopt -q 選項可以忽略錯誤資訊(若指定了一個不在optstring中的選項)
Q:如何在腳本中使用getopt指令?
A:方法是用getopt指令生成的格式化後的版本來替換已有的指令行選項和參數。用set指令能夠做到。
set指令的選項之一是雙破折線(–),它會将指令行參數替換成set指令的指令行值。
該方法會将原始腳本的指令行參數傳給getopt指令,之後再将getopt指令的輸出傳給set指令,用getopt格式化後的指令行參數來替換原始的指令行參數。
其格式如下:
現在原始的指令行參數的值會被getopt指令的輸出替換,而getopt指令以及将原始指令行參數進行了格式化。
notice:
getopt指令并不擅長處理帶空格和引号的參數值。它會将空格當作參數分隔符,而不是根據雙引号将二者當作一個參數。
4.3 使用更進階的getopts–避開getopt指令的劣勢擴充了一些功能
getopts指令(注意是複數)是bash shell的内建。相比getopt指令多了一些擴充功能并且避開了getopt指令不擅長處理帶空格和引号的參數值。
指令 | 差別 |
---|---|
getopt | 1.将指令行上選項和參數處理後隻生成一個輸出 |
getopts | 1.能夠和已有的shell參數變量配合默契 2.一次隻處理指令行上檢測到的一個參數 3.處理完所有參數後,退出并傳回一個大于0的退出狀态碼 4.可以在參數值中包含空格 5.可以将選項字母和參數值放在一起使用而不用加空格 6.能夠将指令行上未定義的選項統一輸出成問号 |
getopts指令格式如下:
getopts optstring variable
notice:
- optstring同樣和getopt一樣也是關鍵;
- 有效的選項字母都會列在optstring中,如果選項字母要求有參數值,就加一個冒号;
- 要去掉錯誤消息,可以在optstring之前加一個冒号,這和getopt指令顯得不同;
- getopts指令将目前參數儲存在variable中;
- getops指令解析指令行選項時會移除開頭的單破折線。
ps:
1.getopts指令會用到兩個環境變量。(OPTARG和OPTIND)
OPTARG環境變量會儲存選項需要跟的參數值;
OPTIND環境變量儲存了參數清單中getopts指令正在處理的參數位置。(getopts指令在處理每個選項時,OPTIND的值會增一)
5.将選項标準化
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAzNfRHLGZkRGZkRfJ3bs92YsYTMfVmepNHL6tGVPNTS61keJpHW4Z0MMBjVtJWd0ckW65UbM5WOHJWa5kHT20ESjBjUIF2X0hXZ0xCMx81dvRWYoNHLrdEZwZ1Rh5WNXp1bwNjW1ZUba9VZwlHdssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49zZuBnL2MTO4IzMyETM0AzMwAjMwIzLc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
6.獲得使用者輸入– read
read
6.1 基本的擷取
read指令從标準輸入(鍵盤)或另一個檔案描述符中接收輸入。
ps:
- echo -n 選項 不會在字元串末尾輸出換行符。
- read指令使用-p選項,允許直接在read指令行指定提示符。(若使用了-p選項而沒有指定提示符,則會出乎所料哦)。
- read指令會将提示符輸入的所有資料配置設定給單個變量(若變量數量不夠,剩下的資料就全部配置設定給最後一個變量,是以要麼指定多個變量,要麼全部配置設定給最後一個變量)。
- 若read指令行中沒有指定變量,則read指令會将它收到的任何資料都放進特殊環境變量REPLY中。
eg:
read -p name
echo $name
read name
echo $name
read -p "Please input you namef: " namef
echo $namef
read -p "Please input you namef: " names
echo $names
read
echo $REPLY
#namewang heng
#
#wang heng
#wang heng
#Please input you namef: wang
#wang
#Please input you namef: heng
#heng
#who
#who
6.2 逾時–read需要逾時判斷
Q:如何做到read逾時判斷?
A:有如下兩種辦法:
- read -t 計時判斷。-t選項指定一個計時器,指定了read指令等待輸入的秒數,當計時器過期後,read指令會傳回一個非零的退出狀态碼。
- 也可以讓read指令來統計輸入的字元數(-n)。當輸入的字元達到預設的字元數時,則自動退出,将輸入指派給變量。
eg:
#read -t
if read -t 5 -p "Please input a num: " num;then
echo "the num is $num"
else
echo "is too slow"
fi
#read -n
read -n1 -p "Continue?[Y/N]" answer #将-n選項和值1一起使用,告訴read指令在接受單個字元後退出
case $answer in
Y | y) echo "continue..";;
N | n) echo
echo "not continue.."
exit;;
esac
echo "shell is over.."
#Please input a num: 2
#the num is 2
#Continue?[Y/N]n
#not continue..
#Please input a num: is too slow
#Continue?[Y/N]ycontinue..
#shell is over..
6.3 隐藏方式讀取– -s
典型應用于密碼輸入上
-s
-s選項可以避免在read指令中輸入的資料出現在顯示器上(實際上,資料會被顯示,隻是read指令會将文本顔色設成跟背景色一樣)
eg:
#read -s
if read -t 5 -s -p "Please input the passwd: " pswd;then
echo "the pswd is $pswd"
else
echo "is too slow"
fi
#Please input the passwd: the pswd is 123
6.4 從檔案讀取
每次調用read指令,它都會從檔案中讀取一行文本。
當檔案中再沒有内容時,read指令會退出并傳回非零退出狀态碼。
Q:如何将檔案内容傳輸給read指令?
A:最常見的方法是對檔案使用cat指令,将結果通過管道直接傳給含有read指令的while指令。
eg:
cnt=1
cat 3_1_while.log | while read line
do
echo "read line$cnt is $line"
cnt=$[ $cnt + 1 ]
done
#read line1 is 5
#read line2 is 4
#read line3 is 3
#read line4 is 2
#read line5 is 1
申明:文中沒特殊注明,圖皆來自Linux指令行與shell腳本程式設計大全<第三版>。