shell腳本語句
運(yùn)算符符
-
運(yùn)算符的使用+ - * /
1. expr是計算整數(shù)類型行的數(shù)據(jù)
2. 運(yùn)算符左右都要有空格
3. ``和$()是取結(jié)果集4. 注意*必須要通過\轉(zhuǎn)義,不然會出錯 5. ``與$()不但可以取整數(shù)運(yùn)算的結(jié)果,還可以取shell命令的結(jié)果集,比如:result= `ls`或者$(ls) 6. result='expr num1 % num2'=num1/num2商...余數(shù) ``` num=1 num1=2 num2=`expr $num + $num1` //num2=`expr $num \* $num1` echo "${num2}" ``` 7. 可以用$((num1+num2)) -
let關(guān)鍵字
num1=1 num2=2 let num3=num1+num2 echo "${num3}"- 可以用在 + - * / % ++ --
- ++ --(都只能用在let里,不能在expr里使用)
- 后綴++
num1=1 let num2=num1++ printf "num1=%s\n" "${num1}" printf "num2=%s\n" "${num2}"http://num2=1,num=2- 前綴++
num1=1 let num2=++num1 printf "num1=%s\n" "${num1}" printf "num2=%s\n" "${num2}"http://num2=2,num=2- 后綴--
num1=1 let num2=num-- printf "num1=%s\n" "${num1}" printf "num2=%s\n" "${num2}"http://num2=1,num=0- 前綴 --
num1=1 let num2=--num printf "num1=%s\n" "${num1}" printf "num2=%s\n" "${num2}"http://num2=0,num=0- +=
num1=1 let num2+=num1 printf "num2=%s\n" "${num2}"http://num2=3
3 . 整數(shù)之間的關(guān)系運(yùn)算符
- \ > \ < \ >= \ <= != ==
- -gt -ge -lt -le -eq -nq
- 在關(guān)系運(yùn)算符中,運(yùn)算結(jié)果是一個邏輯,如果關(guān)系表達(dá)式成立,邏輯值為1,否則為0。
- 除!=,==都要用\轉(zhuǎn)義
- !=可以用\轉(zhuǎn)義也可以不用\轉(zhuǎn)義
- \ =,=,==,==(由編譯器決定,mac支持=,=)
num1=1 num2=2 num3=`expr $num1 \> $num2` echo "${num3}"
關(guān)系運(yùn)算符語句
-
if語句:如果一個數(shù)大于5,然后輸出這個數(shù),否則如果這個數(shù)小于5,然后說明這個數(shù)小于5
if [] then 語句體 elif then 語句體 else 語句體 fi 注意點(diǎn)1. []左右兩邊都要有空格 2. 關(guān)系運(yùn)算符用-gt 等表示printf "請輸入一個數(shù):" read num if [ $num -gt 5 ] then echo "${num}" elif [ $num -lt 5 ] then printf "%s小于5\n" "${num}" else printf "這個數(shù)等于5" fi- 總結(jié):
- else可以沒有,如果有else,必須放在最后面,else下面沒有then
- elif可以沒有,必須要放在if與else中間的位置
- if語句只能執(zhí)行一個分支
- if結(jié)束的標(biāo)志fi
//輸入兩個整數(shù)求最大值輸出
printf "請輸入兩個整數(shù)\n" read num1 read num2 if [ $num1 -gt $num2 ] then printf "最大值為%s\n" "${num1}" else printf "最大值為%s\n" "${num2}" fi - 總結(jié):
-
字符串運(yùn)算符
- =:判斷字符串是否相等
- !=:判斷字符串是否不等
string1="hello" string2="hello" if [ $string1 == $string2 ] then echo "equal" else echo "not equal" fi- -z:zero:判斷字符串是否為空或是不存在
string="" if [ -z $string ] then echo "字符串為空" else echo "字符串不為空" fi -
文件運(yùn)算符
- -d:判斷是否為目錄文件
- -f:判斷是否為普通文件
- -r: 判斷是否可讀
- -w:判斷是否可寫
- -x:判斷是否可執(zhí)行
- -e:exsit:判斷是否存在
//練習(xí):判斷~/share是否存在,如果不存在就創(chuàng)建這個文件,如果存在就提示已存在的信息。
-
case語句
case 變量 in 條件1) 語句體1 ;; 條件2) 語句體2 ;; esacprintf "請輸入一個數(shù)\n" read num case $num in 1) printf "是1" "${num}" ;; 2) printf "是2" "${num}" ;; *) printf "啥都不是" ;; esac- 注意點(diǎn)
- 結(jié)束標(biāo)志必須是esac
- 值1)和值2)可以相同
- 如果值1)和值2)都不滿足,就會來到*)
- *)可以不寫,但要寫就要寫在最后
- 每一個分支結(jié)束都有一個;;
-
數(shù)組
- 數(shù)組的初始化
- 一個變量一個變量進(jìn)行初始化
- array1[0]=8
- array1[1]=9
- 一個一個變量進(jìn)行初始化,可以間隔賦值,還可以不從位置0開始。比如aray1[1]=2,array1[5]=5
- 集體賦值
- array=(1 2 3 4 hello)(可以是不同數(shù)據(jù)類型)
- 一個變量一個變量進(jìn)行初始化
- 數(shù)組元素的訪問
- ${數(shù)組名[下標(biāo)]}
- 遍歷數(shù)組里所有的元素
- ${數(shù)組名[*]||[@]}
a=(1 2 3 4 hello) echo "${a[2]}" echo "${a[@]}" - 數(shù)組的初始化
-
while循環(huán)
while [] do 語句體 donesum=0 i=1 while [ $i -le 100 ] do let sum=sum+i; let i++; done echo "sum=${sum}" -
參數(shù)
- ./XX.sh
- $0:代表執(zhí)行文件./XX.sh
- $1:代表執(zhí)行的第一個參數(shù)
- $2:代表執(zhí)行的第二個參數(shù)
- $n:代表執(zhí)行的第二個參數(shù)
- $#:代表執(zhí)行的參數(shù)個數(shù),不包括命令本身
- ./XX.sh
-
邏輯運(yùn)算符
- && 并且:如果事件1成立并且事件2也成立,整個事件才成立。否則不成立。
- || 或者:兩個事件只要有一個成立,整個事件就成立。
- ! :對事件取反
案例1 printf "請輸入一個數(shù)\n" read num #if [ $((num%5)) -eq 0 ] && [ $((num%3)) -eq 0 ] if [[ $((num%5)) -eq 0 && $((num%3)) -eq 0 ]] #if [ $((num%5)) -eq 0 -a $((num%3)) -eq 0 ](用了-a,-o就可以只用一個[]) then echo "YES" else echo "NO" fi//判斷閏年(能被4整除,且不被100整除,且可以被400整除)
案例2 printf "請輸入一個年份\n" read num if [[ $((num%4)) == 0 && $((num%100)) != 0 ]] || [ $((num%400)) == 0 ] then printf "是閏年" else printf "不是閏年" fi -
for循環(huán)
- 格式:
for 變量 in 參數(shù)列表 do 語句體 done- 遍歷打印當(dāng)前目錄下的子目錄與子文件
value=`ls` for file in $value do echo "${file}" done
10.break:是跳出整個循環(huán)
- 當(dāng)碰到break時,直接跳
出循環(huán),break下面的語句不會被執(zhí)行。
- break只跳出最近的一層循環(huán)
//計算和時只要大于54就退出
```
count=0
while [ $count -le 1 ]
do
i=1
sum=0
while [ $i -le 100 ]
do
if [ $sum -gt 54 ]
then
break
fi
let sum+=i
let i++
done
printf "sum=%s\n" "${sum}"
printf "i=%s\n" "${i}"
let count++
done
```
-
continue
- 當(dāng)碰到continue時,跳出本層循環(huán)當(dāng)前的一次循環(huán),continue下面的語句不會被執(zhí)行
- continue只能存在于循環(huán)中。
//1-20和,跳過3的倍數(shù)
i=1 sum=0 while [ $i -le 20 ] do if [ $((i%10)) == 3 ] then let i++ continue fi let sum+=i let i++ done echo "sum=${sum}" 分析:i=3時,if條件成立,執(zhí)行continue,那么continue下面的語句就不會被執(zhí)行,繼續(xù)返回到while判斷的語句看條件是否成立,如果成立繼續(xù)執(zhí)行 -
死循環(huán)
while: do 語句體 done -
shell函數(shù)
- 函數(shù)調(diào)用之前必須要有相應(yīng)的函數(shù)
- 什么時候用到函數(shù)
- 執(zhí)行的功能類似
- 根據(jù)實(shí)際需求,需要時就用
- shell函數(shù)定義格式
function 函數(shù)名() { }- 調(diào)用函數(shù):直接寫函數(shù)名
- 函數(shù)參數(shù)傳遞
function test() { echo "$0" echo "$1" echo "$2" echo "${10}" echo "hello world" } test 1 2 3 4 5 6 7 8 9 100 分析:1. 當(dāng)參數(shù)作為shell函數(shù)參數(shù)傳遞時,當(dāng)在函數(shù)里面接受n>=10個參數(shù)時,要加上${n} 2. $0不是test,而是shell文件本身 3. 函數(shù)里面的$1與外面的與外面的$1不同,但是函數(shù)里面的$0與函數(shù)外面的$0相同。- 函數(shù)返回值
sum() { num1=$1 num2=$2 let value=num1+num2 return $value } sum 1 2 echo "sun=$?" sum 2 3 echo "sun=$?"http://結(jié)果為sum=3\nsum=5\n 分析:1. **函數(shù)如果是return出來的結(jié)果,我們用$?接受,$?是接受最后運(yùn)行的一次腳本** 2. 如果return后面的值大于255,那么函數(shù)運(yùn)行完后用$?接受,$?=value%256。 3. 怎么接受return出來比255大的值,解決之道:使用echo num 返回出來,函數(shù)外使用變量接收,value=`函數(shù)名`,從而對value進(jìn)行操作。- shell函數(shù)里面可以內(nèi)嵌創(chuàng)建函數(shù)
a() { b() { echo "aaa" } } a b b在什么情況下會被使用,先要調(diào)用a,因?yàn)閍里有b的實(shí)現(xiàn)- 條件函數(shù)
a() { value=1 if [ $value == 1 ] then b() { echo "aaa" } else c() { echo "ccc" } } a b 函數(shù)b和函數(shù)c在什么情況下可以調(diào)用,先運(yùn)行函數(shù)a,因?yàn)閍中有函數(shù)b和函數(shù)c的實(shí)現(xiàn),在if語句條件成立時實(shí)現(xiàn)函數(shù)b的定義;else其他情況實(shí)現(xiàn)函數(shù)c的定義。 - 總結(jié):
- function關(guān)鍵字可以不寫
- shell函數(shù)可以有return,也可以沒有
- 如果return出來的結(jié)果必須要用$?接收
- 如果是用echo保存的結(jié)果集,必須要用value=·test·接收
test()
{
echo 555
}
value=test
echo "test函數(shù)返回值為${value}"
//習(xí)題:求1-100偶數(shù)和
sum=0
i=1
while [ $i -le 100 ]
do
if [ `expr $i % 2` -eq 0 ]
then
let sum=sum+i
fi
let i++
done
echo "sum=${sum}"
//打印99乘法表
i=1
j=1
while [ $i -le 9 ]
do
j=1
while [ $j -le $i ]
do
t=`expr $i \* $j`
printf "%s*%s=%s " "$i" "$j" "$t"
let j++
done
printf "\n"
let i++
done
//輸入兩個整數(shù),再輸入一個+-*/運(yùn)算符,根據(jù)運(yùn)算符,計算兩個數(shù)結(jié)果,用case
printf "輸入兩個整數(shù)"
read i
read j
printf "輸入一個運(yùn)算符"
read s
case $s in
"+")
printf "%s+%s=%s\n" "${i}" "${j}" "$((i+j))"
;;
"-")
printf "%s-%s=%s\n" "${i}" "${j}" "$((i-j))"
;;
"*")
printf "%s*%s=%s\n" "${i}" "${j}" "$((i*j))"
;;
"/")
printf "%s+%s=%s\n" "${i}" "${j}" "$((i/j))"
;;
esac
//打印
*
***
*****
*******
printf "請輸入一個數(shù)\n"
read s
i=1
j=1
while [ $i -le $s ]
do
j=1
while [ $j -le $((s-i)) ]
do
printf " "
let j++
done
k=1
while [ $k -le $((2*i-1)) ]
do
printf "*"
let k++
done
printf "\n"
let i++
done
//腳本編寫小練習(xí):做一個sh 1.sh
- 判斷是否有參數(shù),參數(shù)是否為1
- 判斷文件是否存在
- 如果存在,判斷是否是普通文件
- 如果是普通文件,修改權(quán)限
- 運(yùn)行
- 讓這個命令在全局有效
- chmod 777 XX.sh
- mv XX.sh mysh
- sudo cp mysh /bin
- 附加:判斷是否為.sh文件是再進(jìn)行下一步
value="$1"
lengh=${#value}
value1=${value:$((lengh-3)):3}
if [ $# -eq 0 ]
then
echo "what do you want to do?"
elif [ $# -eq 1 ]
then
if [ -e $1 ]
then
if [ -f $1 ]
then
if [ $value1 == ".sh" ]
then
chmod 777 $1
./$1
else
printf "no .sh\n"
fi
else
echo "no such files"
fi
else
echo "no such files or directory"
fi
else
echo "too much arguements"
fi
今日小結(jié)
昨天剛接觸腳本的時候抱著和其他人一樣的感覺走,只是聽說過腳本這個名詞(游戲腳本現(xiàn)在好像十分流行)卻不知道具體實(shí)現(xiàn)的功能與作用。用法與熟悉的C語言幾乎完全不同,各類操作操碎了我的心。直到下午,親愛的蒼老師叫我們做了一個小練習(xí),自己編寫了一個類似sh作用的腳本直接運(yùn)行.sh文件。讓我醍醐灌頂,原來還可以這么用!不過我說的不是腳本的用法,而是蒼老師編寫程序時思路的用法。原諒我的詞窮,這種東西只可意會不可言傳。在那種思想的領(lǐng)導(dǎo)下,編寫程序時思路比以前升級了1/3,速度比以前提高了1/3,如果將這種思路與方法熟練運(yùn)用。自己的編程能力應(yīng)該可以從中了玄冥神掌半死不活的張無忌升級成練了九陽神功第九重。
$小結(jié)
- 現(xiàn)在假使有函數(shù)
test()
{
value1=$1
value2=$2
}
test year(=$1) mouth(=$2)
輸出結(jié)果為$?
- 假如現(xiàn)在判斷的是執(zhí)行文件后參數(shù)的個數(shù)
./XX.sh year mouth
year=$1
mouth=$2