1. bash shell腳本中的位置變量linux
1. 有些腳本運行時是須要輸入參數的,在shell腳本中加入指定的位置變量,腳本會在運行時讀取位置變量對應的參數,位置變量表示方法以下:shell
(1)$0:表示腳本自身bash
(2)$(basename $0):當咱們使用位置變量$0時,表示將腳本自身名稱做爲變量值傳遞給$0,可是它會傳遞完整的腳本路徑,當咱們僅須要腳本的基名的時候,可使用$(basename $0)來實現less
(3)$1-$9:表示腳本後跟的參數的位置,$1表示第一個參數,$2表示第二個參數以此類推;ide
(4)${#}:#表示大於9的數字,當位置大於9時需使用${}的方式來表示位置this
(5)${!#}:表示腳本最後一個參數做爲變量傳遞給${!#}命令行
(6)$#:表示參數個數統計,$#變量會計算腳本所跟參數的個數對象
(7)$*:表示腳本後跟隨的全部參數,可是它會把這些參數當作一個總體傳遞給$*變量遞歸
(8)$@:與$*相似,一樣是將腳本後所跟隨的全部參數傳遞給$@變量,可是會把每一個變量作爲單個個體依次傳遞給$@。隊列
(9)含空格的參數表示方法:位置變量取值時默認以空格做爲分割,當參數包含空格時,需使用""將該參數引發來,這樣就能夠當成一個獨立的參數傳遞給腳本
(10)shift:腳本參數位移,當在腳本中使用shift時表示將參數的位置向左移動一位
(11)shift n:n用數字表示,shift n表示將參數將左移動n位
2. bash shell腳本位置變量使用示例
2.1 $0
[root@localhost test]# vi test1.sh #!/bin/bash #Testing the $0 parameter # echo "The zero parameter" is set to: $0 ~ "test1.sh" [New] 5L, 81C written [root@localhost test]# chmod u+x test1.sh [root@localhost test]# ./test1.sh The zero parameter is set to: ./test1.sh
根據上述腳本可看出$0的取值爲腳本名 ./test1.sh
2.2 $(basename $0)
[root@localhost test]# vi test2.sh #!/bin/bash #Testing the $(basename $0) parameter # echo "The zero parameter" is set to: $(basename $0) ~ "test2.sh" 5L, 105C written [root@localhost test]# ./test2.sh The zero parameter is set to: test2.sh
根據上述示例可看出使用$(basename $0)後,取得的腳本名僅爲腳本名自己,不包含路徑
2.3 $1-$9
[root@localhost test]# vi test3.sh #!/bin/bash #USing one command line parameter # factorial=1 for (( number=1; number <= $1; number++ )) do factorial=$[ $factorial * $number ] done echo The factorial of $1 is $factorial ~ ~ "test3.sh" 9L, 188C written [root@localhost test]# ./test3.sh 4 The factorial of 4 is 24
根據上述腳本可看出腳本參數4被賦予給了位置變量$1
[root@localhost test]# vi test4.sh #!/bin/bash #Testing tow command lin parameters # if [ $# -ge 3 ] then echo "Please input only tow parameters" elif [ $# -eq 2 ] then if [ $1 -gt $2 ] then echo "$1 is greater than $2" elif [ $1 -eq $2 ] then echo "$1 is equal to $2" else echo "$1 is less than $2" fi else echo "The character you entered is invalid, please enter the number" fi ~ ~ ~ ~ "test4.sh" 20L, 359C written [root@localhost test]# ./test4.sh 4 5 4 is less than 5
經過上述腳本能夠看出$1和$2分別對應位置1和位置2的參數。
2.4 ${#}
當參數個數大於9時,位置變量用${#}表示,#表示大於9的數字
[root@localhost test]# vi test5.sh #!/bin/bash #handing lots of parameters # total=$[ ${10} * ${11} ] echo The tenth parameter is ${10} echo The eleventh parameter is ${11} echo The total is $total ~ ~ "test5.sh" 7L, 163C written [root@localhost test]# ./test5.sh 1 2 3 4 5 6 7 8 9 10 11 The tenth parameter is 10 The eleventh parameter is 11 The total is 110
2.5 $# ${!#}
$#表示參數的個數,${!#}表示最後一個參數
[root@localhost test]# vi test6.sh #!/bin/bash #Grabbing the last parameter # params=$# echo The total number of parameters is $# echo The last parameter is ${!#} ~ ~ "test6.sh" 6L, 128C written [root@localhost test]# ./test6.sh 1 2 4 6 8 9 10 4 The total number of parameters is 8 The last parameter is 4
根據上述腳本和執行結果和看出$#最後顯示的是參數的總個數,爲8個,${!#}顯示的是最後一個參數,爲4。${!#}還有一個特殊特性,當腳本後沒有參數時將返回腳本名。
2.6 $* $@
$*和$@都表示全部參數,可是$*表示將全部參數當作一個總體傳遞給$*,而$@則表示將每一個參數按順序一個個傳遞給$@
[root@localhost test]# vi test7.sh #!/bin/bash #Testing $* and $@ # count=1 # for params in "$*" do echo "\$* Paramter #$count = $params" count=$[ $count + 1 ] done # # count=1 for params in "$@" do echo "\$@ Parameter #$conut = $params" count=$[ $count + 1 ] done ~ ~ ~ "test7.sh" 18L, 234C written [root@localhost test]# ./test7.sh rich barbara katie jessica $* Paramter #1 = rich barbara katie jessica $@ Parameter # = rich $@ Parameter # = barbara $@ Parameter # = katie $@ Parameter # = jessica
根據上述腳本能夠看到咱們分別爲$*和$#設置了for循環,從隊列$*讀取的變量值是將參數做爲一個總體,而從$@中是逐個參數船體給$@
2.7 shift n
在shell腳本中shift的做用是將指定位置的參數向左移動,n爲移動的位置數,若是沒有設置n,則默認爲1
[root@localhost test]# vi test8.sh #!/bin/bash #Testing shift # count=1 for params in "$@" do echo "#$count = $1" count=$[ $count + 1 ] shift done ~ ~ "test8.sh" 10L, 115C written [root@localhost test]# ./test8.sh rich barbara katie jessica #1 = rich #2 = barbara #3 = katie #4 = jessica
根據上述腳本可看出每一執行完一輪循環shift都會將參數左移一位,$1位置的參數在位移後會丟失。$1會讀取原$1位置的後一位參數。
[root@localhost test]# vi test9.sh #!/bin/bash #Demonstrating a multi-position shift # echo "The original parameter: $*" shift 2 echo "Here's the new first parameter: $1" ~ ~ "test9.sh" [New] 6L, 136C written [root@localhost test]# chmod u+x test9.sh [root@localhost test]# ./test9.sh 1 2 3 4 5 The original parameter: 1 2 3 4 5 Here's the new first parameter: 3
根據上述腳本可看出當使用shift 2 後,參數向左移動了2位,全部移動後的$1爲3
3. 處理命令行選項
3.1 處理簡單選項
可使用while循環檢查選項,使用case命令按照條件輸出選項所對應的操做。
[root@localhost test]# vi test1.sh #!/bin/bash #Testing simple parameter processing # while [ -n "$1" ] do case "$1" in -a ) echo "Found the -a option" ;; -b ) echo "Found the -b option" ;; -c ) echo "Found the -c option" ;; * ) echo "The $1 is not an option" ;; esac shift done ~ ~ ~ [root@localhost test]# ./test1.sh -a -b -c -d Found the -a option Found the -b option Found the -c option The -d is not an option
3.2 分離選項和參數
可以使用使用 -- 號來分離選項和參數當遇到 -- 時終止while循環,同時把 -- 使用shift命令移除
[root@localhost test]# vi test2.sh #!/bin/bash #Testing simple parameter processing # while [ -n "$1" ] do case "$1" in -a ) echo "Found the -a option" ;; -b ) echo "Found the -b option" ;; -c ) echo "Found the -c option" ;; -- ) shift break ;; * ) echo "The $1 is not an option" ;; esac shift done # count=1 for parameter in "$@" do echo "The #$parameter is a parameter" count=$[ $count + 1 ] done ~ ~ "test2.sh" 22L, 381C written [root@localhost test]# ./test2.sh -c -b test1 test2 test3 Found the -c option Found the -b option The test1 is not an option The test2 is not an option The test3 is not an option [root@localhost test]# ./test2.sh -c -a -- test1 test2 test3 Found the -c option Found the -a option The #test1 is a parameter The #test2 is a parameter The #test3 is a parameter
3.3 處理帶參數的選項
[root@localhost test]# vi test3.sh #!/bin/bash # extracting command line options and values # while [ -n "$1" ] do case "$1" in -a) echo "Found the -a options";; -b) parameter="$2" echo "Found the -b options , with parameter values $parameter" shift;; -c) echo "Found the -c options";; --) shift break;; *) echo "$1 is not options";; esac shift done # count=1 for parameter in "$@" do echo #$parameter is a parameter count=$[ $count + 1 ] done ~ ~ "test3.sh" 24L, 442C written [root@localhost test]# ./test3.sh -a -b test1 -d Found the -a options Found the -b options , with parameter values test1 -d is not options
3.4 getopt命令
getopt命令能夠接受任何選項和參數,並將他們轉換成相應的格式
格式:getopt OPTSRING parameter
帶參數的選項後跟:
示例:
[root@localhost test]# getopt ab:cd -a -b test1 -cd test2 test3 test4 -a -b test1 -c -d -- test2 test3 test4
要在腳本中使用getopt命令,須要使用set命令
示例:(-q 命令表示忽略錯誤提示,--會將命令行參數替換成set的命令行值)
set -- $(getopt -q -ab:cd "$@")
腳本示例以下:
[root@localhost test]# vi test4.sh #!/bin/bash #Extract command line options & values with getopt # set -- $(getopt -q ab:cd "$@") while [ -n "$1" ] do case "$1" in -a) echo "Found the -a options";; -b) parameter=$2 echo "Found the -b options with parameter value $parameter" shift;; -c) echo "Found the -c options";; -d) echo "Found the -d options";; --) shift break;; *) echo "$1 is not option";; esac shift done # count=1 for parameter in "$@" do echo "The #$parameter is a parameter" count=$[ $count + 1 ] done ~ "test4.sh" 26L, 516C written [root@localhost test]# ./test4.sh -a -b test1 -c -d test3 test4 test5 test6 Found the -a options Found the -b options with parameter value 'test1' Found the -c options Found the -d options The #'test3' is a parameter The #'test4' is a parameter The #'test5' is a parameter The #'test6' is a parameter
根據上述可看出getopt命令能夠自動識別參數、選項,無需使用--來隔開參數。
可是getopt存在缺陷,例如一樣運行上述腳本執行如下參數,結果可能會出現誤差
示例:
[root@localhost test]# ./test4.sh -a -b "test1 test2" -cd test3 test4 Found the -a options Found the -b options with parameter value 'test1 test2' is not option #test1和test2同爲-b選項的參數,但僅能識別test1,getopt不能識別"" Found the -c options Found the -d options The #'test3' is a parameter The #'test4' is a parameter
經過上述腳本執行結果可發現getopt不能識別「」,用「」引發來的參數不會被當成同一個參數來對待。
3.5 getopts
getopts命令至關於getopt命令的升級版,可是getopts和getopt存在乳以下差別:
(1)getopt會將全部輸入選項和參數一次性輸出,可是getopts一次只處理一個參數或選項,輸出完成後會返回一個大於0的退出碼;
(2)getopts忽略錯誤的方式是在OPTstring以前加:,而getopt忽略錯誤的方式是加-q選項
命令格式: getopts OPTSTRING parameter
(3)getopts會將「」下的參數當成一個參數來輸出
(4)getopts會自動移除--選項,因此case中的條件無需指定--
(5)getopts能夠將選項和參數輸入到一塊兒,無需空格隔開
(6)對於未識別的選項和參數會返回?
(7)getopts命令會用到兩個環境變量。若是選項須要跟一個參數值,OPTARG環境變量就會保存這個值。OPTIND環境變量保存了參數列表中getopts正在處理的參數位置。這樣你就能在處理完選項以後繼續處理其餘命令行參數
示例1:
[root@localhost test]# vi test5.sh #!/bin/bash #simple demonstration of the getopts command # while getopts :ab:c opt do case "$opt" in a) echo "Found the -a option";; b) echo "Found the -b option with VALUE $OPTARG";; c) echo "Found the -c option";; *) echo "Unknow option : $opt ";; esac done ~ "test5.sh" 12L, 271C written [root@localhost test]# ./test5.sh -a -b test1 -c Found the -a option Found the -b option with VALUE test1 Found the -c option [root@localhost test]# ./test5.sh -a -b "test1 test2" -c Found the -a option Found the -b option with VALUE test1 test2 Found the -c option [root@localhost test]# ./test5.sh -d Unknow option : ?
getopts命令知道什麼時候中止處理選項,並將參數留給你處理。在getopts處理每一個選項時,它會將OPTIND環境變量值增一。在getopts完成處理時,你可使用shift命令和OPTIND值來移動參數。
示例:
[root@localhost test]# vi test6.sh #!/bin/bash #Processing options & parameters with getopts # while getopts :ab:cd opt do case "$opt" in a) echo "Found the -a option";; b) echo "Found the -b option with parameter is $OPTARG";; c) echo "Found the -c option";; d) echo "Found the -d option";; *) echo "Unknow options";; esac done shift $[ $OPTIND - 1 ] # count=1 for parameter in "$@" do echo "Parameter #$count : $parameter" count=$[ $count + 1 ] done ~ "test6.sh" 21L, 431C written [root@localhost test]# ./test6.sh -a -b test1 -c -d test3 test4 Found the -a option Found the -b option with parameter is test1 Found the -c option Found the -d option Parameter #1 : test3 Parameter #2 : test4
3.6 選項標準化
linux中有一些比較通用的選項,若是咱們的腳本支持這些選項對用戶來講將變的更友好
-a : 顯示全部對象
-c : 生成一個計數器
-d : 指定一個目錄
-e : 擴展一個對象
-f : 指定一個輸入數據的文件
-h : 顯示該命令的幫助信息
-i : 忽略文本大小寫
-l : 輸出長格式版本
-n : 使用非交互模式輸出(批處理)
-o : 將輸出內容重定向輸出至指定文件
-q : 以安靜模式運行
-r : 遞歸的處理目錄和文件
-s : 以安靜模式運行
-v :生成詳細輸出
-x : 排除某個對象
-y : 對全部問題都回答YES
4. 得到用戶的輸入
4.1 得到用戶的基本輸入
可使用read命令得到用戶的輸入
示例
[root@localhost test]# vi test7.sh #!/bin/bash #Testing the read command # echo -n "Enter your name:" read name echo "Hello $name , welcome to my program ! " ~ ~ "test7.sh" [New] 6L, 123C written [root@localhost test]# chmod o+x test7.sh [root@localhost test]# ./test7.sh Enter your name:liuxingyue Hello liuxingyue , welcome to my program !
根據上述腳本可看出read 能夠將接受用戶輸入的參數賦予給read命令後的變量,echo後的-n參數表示在字符串末尾輸出換行符;
初此以外read 還可使用-p命令接受用戶輸入的參數
示例
[root@localhost test]# vi test8.sh #!/bin/bash #Testing "read -p" command # read -p "Please input your age :" age day=$[ $age * 365 ] echo "That makes your over $day days old !" ~ "test8.sh" 6L, 144C written [root@localhost test]# ./test8.sh Please input your age :33 That makes your over 12045 days old !
上述示例處理的只是單個變量,若是用戶輸入多個參數,read能夠將參數依次匹配到指定變量,若是輸入參數個數比變量個數多,則會將最後的參數所有匹配到最後的變量中
示例
[root@localhost test]# vi test9.sh #!/bin/bash # ENtering multiple variables # read -p "Enter your name :" first last echo "Welcome $first $last..." ~ ~ "test9.sh" [New] 5L, 114C written [root@localhost test]# chmod o+x test9.sh [root@localhost test]# ./test9.sh Enter your name :liu xingyue hehe Welcome liu xingyue hehe...
read命令會將用戶輸入的參數存入到REPLY變量中,若是read不指定變量,使用$REPLY變量也能夠。
示例
[root@localhost test]# ./test10.sh Enter your name :wangyanglin ^H wangyanglin , Wlecome to my program [root@localhost test]# vi test10.sh #!/bin/bash #Testing $REPLY # read -p "Enter your name :" echo "$REPLY , Wlecome to my program" ~ ~ "test10.sh" 5L, 97C written [root@localhost test]# ./test10.sh Enter your name :hah heh hoh hah heh hoh , Wlecome to my program [root@localhost test]# ^C [root@localhost test]#
4.2 輸入超時控制
read -t #命令經過-t選項指定一個計數器,#表示秒數,加入#爲5,則表示5秒以內若是用戶沒有輸入會自動退出腳本並返回一個非零的退出狀態碼
示例:
[root@localhost test]# vi test11.sh #!/bin/bash #Test the -t option # read -t 5 -p "Enter your name :" echo "$REPLY , Welcome to my program" ~ ~ ~ "test11.sh" [New] 5L, 105C written [root@localhost test]# chmod o+x test11.sh [root@localhost test]# ./test11.sh Enter your name : , Welcome to my program
read -n# 選項能夠定義輸入的字符個數,#爲1,則表示僅只能輸入一個字符。
[root@localhost test]# vi test12.sh #!/bin/bash #getting just one character of input read -n1 -p"Do you want contine [Y/N] ?" case $REPLY in y|Y) echo "Fine,contine to .......";; n|N) echo "OK , bye !" exit;; *) echo "Input error" exit;; esac echo "This is the end of the script" ~ "test12.sh" 11L, 257C written [root@localhost test]# ./test12.sh Do you want contine [Y/N] ?yFine,contine to ....... This is the end of the script [root@localhost test]# ./test12.sh Do you want contine [Y/N] ?nOK , bye ! [root@localhost test]# ./test12.sh Do you want contine [Y/N] ?eInput error
4.3 隱藏式輸入
read命令的 -s參數能夠實現輸入隱藏,腳本運行時你輸入的內容不會顯示出來(其實是顯示的,只是顏色與背景色同樣),通常會用於輸入密碼或者其餘場景。
示例:
[root@localhost test]# vi test13.sh #!/bin/bash #Testing the "-s" option. # read -s -p "Please input your password:" pass echo "Your password is $pass" ~ ~ "test13.sh" 5L, 116C written [root@localhost test]# ./test13.sh Please input your password:Your password is nihao
4.4 read讀取文本輸入,可使用while循環,文本輸入完成之後,自動結束命令
示例:
[root@localhost test]# vi test14.sh #!/bin/bash #Testing text input with read command # count=1 cat test | while read line do echo "Line #$count : $line" count=$[ $count +1 ] done echo "Finished processing the file." ~ ~ ~ "test14.sh" [New] 10L, 183C written [root@localhost test]# cat test ck brown dog jumps over the lazy fox. This is a test, this is only a test. O Romeo, Romeo! Wherefore art thou Romeo? [root@localhost test]# ./test14 -bash: ./test14: No such file or directory [root@localhost test]# ./test14.sh Line #1 : ck brown dog jumps over the lazy fox. Line #2 : This is a test, this is only a test. Line #3 : O Romeo, Romeo! Wherefore art thou Romeo? Finished processing the file.