如何建設(shè)網(wǎng)站效果好百度發(fā)布信息的免費(fèi)平臺(tái)
一、基本介紹
1、如何傳遞參數(shù)
向shell腳本傳遞數(shù)據(jù)的最基本方法就是通過(guò)命令行參數(shù)。如下,這條命令會(huì)向test.sh腳本傳遞10和20這兩個(gè)參數(shù)。
./test.sh 10 20
?2、如何讀取參數(shù)
bash shell會(huì)將所有的命令行參數(shù)都指派給稱(chēng)作位置參數(shù)(positional parameter)的特殊變量,包括shell腳本名稱(chēng)。
$0:對(duì)應(yīng)腳本名;
$1:對(duì)應(yīng)第一個(gè)命令行參數(shù)
$2:對(duì)應(yīng)第二次命令參數(shù)
以此類(lèi)推,直到$9
#!/bin/bash#計(jì)算階乘
factorial=1
for (( a = 1; a <= $1; a++ ))
dofactorial=$[ $factorial * $a ]
done
echo "$1的階乘是$factorial."
因?yàn)閭魅氲膮?shù)之間是以空格分隔的,如果傳入的參數(shù)帶有空格,就需要使用引號(hào)。
#!/bin/bashecho "Hello $1, you are a good man."
exit
3、參數(shù)超過(guò)9個(gè)
如果想要傳入的參數(shù)超過(guò)9個(gè),需要在第9個(gè)位置變量后,在變量名的兩側(cè)加上花括號(hào),如${10}。
#!/bin/bashproduct=$[ ${10} * ${11} ]
echo "第10個(gè)參數(shù)是${10}."
echo "第11個(gè)參數(shù)是${11}."
echo "product的值是$product."
exit
4、讀取腳本名
?如下示例會(huì)將命令名或絕對(duì)路徑都當(dāng)成是腳本的名稱(chēng)。
#!/bin/bashecho "腳本的名字是:$0"
exit
bashname命令能返回不包含命令名或絕對(duì)路徑的腳本名。?
#!/bin/bash#使用basename返回不包含路徑的shell腳本名
shellname=$(basename $0)
echo "腳本名字是:$shellname"
exit
?
5、檢查命令行參數(shù)是否為空
#!/bin/bashif [ -n "$1" ] #檢查命令行第一個(gè)參數(shù)是否為空
thenfactorial=1for (( a = 1; a <= $1; a++ ))dofactorial=$[ $factorial * $a ]doneecho "$1的階乘是$factorial."
elseecho "你沒(méi)有提供命令行參數(shù)。"
fi
exit
二、特殊參數(shù)變量
1、$#
特殊變量$#可以獲取到shell腳本運(yùn)行時(shí)攜帶的命令行參數(shù)的數(shù)量。
#!/bin/bashif [ $# -ne 2 ]
thenecho "shell腳本$(basename $0)提供的命令行參數(shù)不夠。"
elsetotal=$[ $1 + $2 ]echo "兩個(gè)命令行參數(shù)的和是$total"
fi
exit
?2、${!#}
${!#}獲取命令行中的最后一個(gè)參數(shù)。
#!/bin/bashecho "總共有$#個(gè)命令行參數(shù)。"
echo "其中命令行的最后一個(gè)參數(shù)是${!#}。"
exit
3、$*和$@
?$*變量會(huì)將所有的命令行參數(shù)視為一個(gè)單詞,而這個(gè)單詞會(huì)包含命令行中出現(xiàn)的每一個(gè)參數(shù)。$*變量會(huì)將這些參數(shù)視為一個(gè)整體,而不是一系列個(gè)體。
$@變量則會(huì)將所有的命令行參數(shù)視為同一字符串中的多個(gè)獨(dú)立的單詞,方便遍歷訪問(wèn)。
當(dāng)$*出現(xiàn)在雙引號(hào)內(nèi)時(shí),會(huì)被擴(kuò)展成由多個(gè)命令行參數(shù)組成的單個(gè)單詞,每個(gè)參數(shù)之間以IFS變量值的第一個(gè)字符分隔,即,“$*”會(huì)被擴(kuò)展為“$1c$2c$3c...”(其中c是IFS變量值的第一個(gè)字符)
當(dāng)$@出現(xiàn)在雙引號(hào)內(nèi)時(shí),它所包含的各個(gè)命令行參數(shù)會(huì)被擴(kuò)展成獨(dú)立的單詞,即,“$@”會(huì)被擴(kuò)展為"$1""$2""$3"...
#!/bin/bashecho "使用\$*方法,參數(shù)是:$*"
count=1
for param in "$*"
doecho "\$*方法參數(shù)#$count = $param"count=$[ $count + 1 ]
done
#!/bin/bashecho "使用\$@方法,參數(shù)是:$@"
count=1
for param in "$@"
doecho "\$@方法參數(shù) #$count = $param."count=$[ $count + 1 ]
done
echo
exit
?
4、移動(dòng)參數(shù)shift命令
shift命令可以根據(jù)命令行參數(shù)的相對(duì)位置進(jìn)行移動(dòng)。默認(rèn)情況下,它會(huì)將每個(gè)位置的變量值都向左移動(dòng)一個(gè)位置,$3的值移入$2,$2的值移入$1,$1的值會(huì)被刪除(變量$0的值是腳本名,不會(huì)改變)。如果某個(gè)參數(shù)被移除后,那么它的值就被丟棄而無(wú)法恢復(fù)了。
通過(guò)shift命令可以用來(lái)遍歷命令行參數(shù),尤其是在不知道到底有多少參數(shù)的時(shí)候,可以只操作第一個(gè)位置變量,移動(dòng)參數(shù),然后繼續(xù)處理該變量。
#!/bin/bashecho #打印空行
echo "使用shift命令進(jìn)行移位操作。"
count=1
while [ -n "$1" ] #測(cè)試第一個(gè)參數(shù)值的長(zhǎng)度,當(dāng)長(zhǎng)度為0時(shí),結(jié)束循環(huán)
doecho "參數(shù) #$count = $1"count=$[ $count + 1 ]shift
done
echo
exit
一次性移動(dòng)多個(gè)位置,只需給shift命令提供一個(gè)參數(shù),指明要移動(dòng)的位置數(shù):?shift n
#!/bin/bashecho
echo "所有的命令行參數(shù)是:$@"
echo "現(xiàn)在向左移動(dòng)兩位。"
shift 2
echo "移位后第一個(gè)參數(shù)是:$1"
echo
exit
?
三、處理bash命令中的選項(xiàng)
命令行參數(shù)是在命令/腳本名之后出現(xiàn)的各個(gè)單詞,其中,以連字符(-)或雙連字符(--)起始的參數(shù),因?yàn)樗鼈兡軌蚋淖兠畹男袨?#xff0c;所以稱(chēng)作為命令行選項(xiàng)。命令行選項(xiàng)是一種特殊形式的命令行參數(shù)。
1、處理簡(jiǎn)單命令行選項(xiàng)
同樣可以使用shift命令處理命令行選項(xiàng)。
#!/bin/bashecho
while [ -n $1 ]
docase "$1" in-a) echo "找到-a命令行選項(xiàng)。";;-b) echo "找到-b命令行選項(xiàng)。";;-c) echo "找到-c命令行選項(xiàng)。";;*) echo "$1不是一個(gè)命令行選項(xiàng)。";;esacshift
done
echo
exit
2、分離命令行參數(shù)和選項(xiàng)
在Linux中,可以使用雙連字符(--)將命令行選項(xiàng)和參數(shù)分開(kāi)。
#!/bin/bashecho
while [ -n "$1" ]
docase "$1" in-a) echo "-a是命令行選項(xiàng)";;-b) echo "-b是命令行選項(xiàng)";;-c) echo "-c是命令行選項(xiàng)";;--) shift #在遇到雙連字符時(shí)需要將其移出位置變量,然后用break跳出while循環(huán)break;;*) echo "$1不是命令行選項(xiàng)"esacshift
doneecho
count=1
for param in $@
doecho "參數(shù)#$count:$param"count=$[ $count + 1 ]
done
echo
exit
不使用雙連字符時(shí)?
使用雙連字符時(shí)
?
3、處理含參數(shù)的選項(xiàng)
?有些命令行選項(xiàng)需要一個(gè)額外的參數(shù)值。如下所示:
#!/bin/bashecho
while [ -n "$1" ]
docase "$1" in-a) echo "-a是命令行選項(xiàng)";;-b) param=$2echo "-b是命令行選項(xiàng),且?guī)е鴧?shù)$param"shift;;-c) echo "-c是命令行選項(xiàng)";;--) shift #在遇到雙連字符時(shí)需要將其移出位置變量,然后用break跳出while循環(huán)break;;*) echo "$1不是命令行選項(xiàng)"esacshift
doneecho
count=1
for param in $@
doecho "參數(shù)#$count:$param"count=$[ $count + 1 ]
done
echo
exit
由于要處理的命令行選項(xiàng)位于$1,那么額外的參數(shù)值就應(yīng)該在$2(前面所有的參數(shù)在處理完之后都會(huì)被移出),所以只要從$2變量中提取出來(lái)就可以了。最后,因?yàn)檫@個(gè)命令行選項(xiàng)占用了兩個(gè)位置,所以還需要使用shift命令多移動(dòng)一次。?
只要記住放置好相應(yīng)的命令行選項(xiàng)參數(shù),無(wú)論按什么順序放置命令行選項(xiàng)都可以。如下所示:?
4、getopt命令
?介紹
getopt命令可以接受一系列任意形式的命令行選項(xiàng)和參數(shù),并自動(dòng)將其轉(zhuǎn)換成適當(dāng)?shù)男问健?/p>
格式:
getopt optstring parameters
optstring定義了有效的命令行選項(xiàng)的字母,同時(shí)也定義了哪些命令行選項(xiàng)需要參數(shù)值。
先在optstring里列出要在腳本中用到的每個(gè)命令行選項(xiàng)字母,其次在每個(gè)需要參數(shù)值的選項(xiàng)字母后面加一個(gè)冒號(hào)。
?示例:getopt ab:cd -a -b Bparam -cd test1 test2
optstring定義了4個(gè)有效的命令行選項(xiàng)字母:a、b、c、d。冒號(hào)(:)放在了字母b的后面,表明b命令行選項(xiàng)需要一個(gè)參數(shù)值。當(dāng)getopt命令運(yùn)行時(shí),會(huì)檢查參數(shù)列表(-a -b Bparam -cd test1 test2),并基于提供的optstring進(jìn)行解析。它會(huì)自動(dòng)將-cd分成兩個(gè)單獨(dú)的命令行選項(xiàng),并插入雙連字符來(lái)分隔命令行中額外的參數(shù)。
如果optstring未包含用戶(hù)指定的選項(xiàng),就會(huì)報(bào)錯(cuò)。
如果想忽略這條報(bào)錯(cuò),使用選項(xiàng)-q:
?在腳本中如何使用
可以借助能夠處理shell中各種變量的set命令。
set命令有一個(gè)選項(xiàng)是雙連字符(--),它可以將位置變量的值替換成set命令所指定的值。
首先,將腳本的命令行參數(shù)傳給getopt命令;然后再將getopt命令的輸出傳給set命令,用getopt格式化后的命令行參數(shù)來(lái)替換原始的命令行參數(shù)。
set -- $(getopt -q ab:cd "$@")
#!/bin/bash
set -- $(getopt -q ab:cd "$@")echo
while [ -n "$1" ]
docase "$1" in-a) echo "-a是命令行選項(xiàng)";;-b) param=$2echo "-b是命令行選項(xiàng),且?guī)е鴧?shù)$param"shift;;-c) echo "-c是命令行選項(xiàng)";;--) shift #在遇到雙連字符時(shí)需要將其移出位置變量,然后用break跳出while循環(huán)break;;*) echo "$1不是命令行選項(xiàng)"esacshift
doneecho
count=1
for param in $@
doecho "參數(shù)#$count:$param"count=$[ $count + 1 ]
done
echo
exit
5、getopts命令
?getopt的缺點(diǎn)在于不擅長(zhǎng)處理帶空格和引號(hào)的參數(shù)值,如果遇到后,它會(huì)將空格當(dāng)做參數(shù)分隔符,而不是根據(jù)引號(hào)將二者當(dāng)做一個(gè)參數(shù)。
getopt與getopts的區(qū)別:前者在將命令行中的選項(xiàng)和參數(shù)處理后只生成一個(gè)輸出,而后者能夠和已有的shell位置變量配合默契。
getopts每次只會(huì)處理一個(gè)檢測(cè)到的命令行參數(shù),在處理完所有的參數(shù)后,getopts就會(huì)退出,同時(shí)返回一個(gè)大于0的退出狀態(tài)碼。使其非常適合用在解析命令行參數(shù)的循環(huán)中。
格式:
getopts optstring variable
optstring的用法與在getopt里的一致,不同的是,如果不想顯示錯(cuò)誤消息的話,可以在optstring之前加一個(gè)冒號(hào)。optstring中未定義的選項(xiàng)字母會(huì)以問(wèn)號(hào)的形式傳給腳本。
getopts命令會(huì)將當(dāng)前參數(shù)保存在命令行中定義的variable中。
getopts命令需要用到兩個(gè)環(huán)境變量:OPTARG和OPTIND;前者保存選項(xiàng)加帶的參數(shù)值,后者保存參數(shù)列表中g(shù)etopts正在處理的參數(shù)位置,這樣在處理完當(dāng)前選項(xiàng)之后就能繼續(xù)處理其他命令行參數(shù)了。
#!/bin/bashecho
while getopts :ab:c opt
docase "$opt" ina) echo "-a是命令行選項(xiàng)";;b) echo "-b是命令行選項(xiàng),且?guī)е鴧?shù)值$OPTARG";;c) echo "-c是命令行選項(xiàng)";;*) echo "未知的命令行選項(xiàng):$opt";;esac
done
exit
在解析命令行選項(xiàng)時(shí),getopts命令會(huì)移除起始的連字符(-),所以在case語(yǔ)句中不用連字符。
可以在參數(shù)值中加入空格
可以將命令行選項(xiàng)字母與參數(shù)值寫(xiě)在一起,且兩者之間不加空格。
getopts命令可以將在命令行中找到的所有未定義的命令行選項(xiàng)統(tǒng)一輸出成問(wèn)號(hào)。
?
getopts命令知道何時(shí)停止處理命令行選項(xiàng),并將參數(shù)值留給用戶(hù)處理。在處理每個(gè)選項(xiàng)時(shí),getopts都會(huì)將OPTIND環(huán)境變量值加1,處理完選項(xiàng)后,就可以使用shift命令和OPTIND值來(lái)移動(dòng)參數(shù)。
#!/bin/bashecho
while getopts :ab:cd opt
docase "$opt" ina) echo "-a是命令行選項(xiàng)";;b) echo "-b是命令行選項(xiàng),且?guī)е鴧?shù)值$OPTARG";;c) echo "-c是命令行選項(xiàng)";;d) echo "-d是命令行選項(xiàng)";;*) echo "未知的命令行選項(xiàng):$opt";;esac
doneshift $[ $OPTIND - 1 ]
echo
count=1
for param in "$@"
doecho "參數(shù)#$count:$param"count=$[ $count + 1 ]
done
echo
exit
?
?四、常用的Linux命令行選項(xiàng)
-a | 顯示所有對(duì)象 |
-c | 生成計(jì)數(shù) |
-d | 指定目錄 |
-e | 擴(kuò)展對(duì)象 |
-f | 指定讀入數(shù)據(jù)的文件 |
-h | 顯示命令的幫助信息 |
-i | 忽略文本大小寫(xiě) |
-l | 產(chǎn)生長(zhǎng)格式輸出 |
-n | 使用非交互模式(批處理) |
-o | 將所有輸出重定向至指定的文件 |
-q | 以靜默模式運(yùn)行 |
-r | 遞歸處理目錄和文件 |
-s | 以靜默模式運(yùn)行 |
-v | 生成詳細(xì)輸出 |
-x | 排除某個(gè)對(duì)象 |
-y | 對(duì)所有問(wèn)題回答yes |
五、獲取用戶(hù)輸入
有時(shí)候腳本需要用戶(hù)更多的交互性,比如在腳本運(yùn)行時(shí)詢(xún)問(wèn)用戶(hù)并等待用戶(hù)的回答。
1、read命令
read命令從標(biāo)準(zhǔn)輸入(鍵盤(pán))或另一個(gè)文件描述符中接受輸入,獲取到輸入后,它會(huì)將數(shù)據(jù)存入變量。
#!/bin/bashecho -n "請(qǐng)輸入你的名字:" # -n選項(xiàng)不會(huì)在字符串末尾輸出換行符,允許腳本用戶(hù)緊跟其后輸入數(shù)據(jù)read name
read -p "請(qǐng)輸入你的年齡:" age # -p選項(xiàng)允許直接指定提示符。
days=$[ $age * 365 ]echo "你好,$name. 恭喜你,已經(jīng)活了$days天。"
exit
read命令會(huì)將提示符后輸入的所有數(shù)據(jù)分配給單個(gè)變量。如果指定多個(gè)變量,則輸入的每個(gè)數(shù)據(jù)值都會(huì)分配給變量列表中的下一個(gè)變量,如果變量數(shù)量不夠,則剩下的數(shù)據(jù)就全部分配給最后一個(gè)變量。
#!/bin/bashread -p "請(qǐng)輸入你的姓與名:"family_name last_name
echo "你的姓是$family_name,名是$last_name"
exit
read命令中也可以不指定任何變量,如此read命令就會(huì)將接收到的所有數(shù)據(jù)都放進(jìn)特殊環(huán)境變量REPLY中。REPLY環(huán)境變量包含輸入的所有數(shù)據(jù)。
#!/bin/bashread -p "請(qǐng)輸入你的姓名:"
echo
echo "你好,$REPLY!"
exit
2、超時(shí)
?如果用戶(hù)一直不輸入,那么read命令就會(huì)一直等待,此時(shí)可以用 -t 選項(xiàng)指定計(jì)時(shí)器,如果計(jì)時(shí)器超時(shí),read命令會(huì)返回一個(gè)非0的退出狀態(tài)碼。
#!/bin/bashif read -t 5 -p "請(qǐng)輸入你的姓名:" name
thenecho "你的姓名是:$name"
elseechoecho "你一直沒(méi)有輸入,所以不再繼續(xù)等待。"
fi
exit
使用read命令的 -n 選項(xiàng)統(tǒng)計(jì)輸入的字符個(gè)數(shù),當(dāng)字符個(gè)數(shù)達(dá)到預(yù)期值時(shí),就自動(dòng)退出腳本,并將已輸入的數(shù)據(jù)賦給變量。
#!/bin/bash# -n 1告訴read命令在接收到單個(gè)字符后就退出。
read -n 1 -p "你是否想繼續(xù)?[Y/N]" answercase $answer inY | y) echoecho "好的,請(qǐng)繼續(xù)……";;N | n) echoecho "好的,結(jié)束。"exit;;
esac
echo "腳本已結(jié)束。"
exit
?3、無(wú)顯示讀取
從用戶(hù)處得到輸入,但不想在屏幕上顯示出用戶(hù)的輸入信息,比如,輸入密碼。
-s 選項(xiàng)可以讓在read命令中輸入的數(shù)據(jù)出現(xiàn)在屏幕上(其實(shí)數(shù)據(jù)還是會(huì)被顯示,只不過(guò)read命令將文本顏色設(shè)成了和背景色一樣)
#!/bin/bashread -s -p "請(qǐng)輸入你的密碼:" passwd
echo
echo "你的密碼是:$passwd"
exit
4、讀取文件
可以使用read命令讀取文件。每次調(diào)用read命令都會(huì)從指定文件中讀取一行文本。當(dāng)文本中沒(méi)有內(nèi)容可讀時(shí),read命令會(huì)退出并返回一個(gè)非0的退出狀態(tài)碼。
如何將文件的數(shù)據(jù)傳遞給read命令,最常見(jiàn)的方法是對(duì)文件使用cat命令,然后將結(jié)果通過(guò)管道直接傳給含有read命令的while命令。
#!/bin/bashcount=1
cat $HOME/ning/test.txt | while read line
doecho "Line $count:$line"count=$[ $count + 1 ]
done
echo "已處理完該文件。"
exit