1. 程式人生 > >Linux中的shell指令碼

Linux中的shell指令碼

shell 指令碼:通常指的是在linux版本伺服器中編寫的指令碼。shell 指令碼本看成使用者和系統之間的溝通橋樑。

shell屬於解釋型語言。

直譯器型別有:
/bin/sh
/bin/bash
/bin/ksh
/bin/csh
等。

常用和絕大多數linux核心系統預設使用bash

shell指令碼執行方式:
1、授予指令碼可執行的許可權
chmod a+x ./first.sh  : 授予可執行許可權
./first.sh  : 執行./first.sh指令碼

2、使用直譯器執行:
bash ./first.sh : 使用bash解釋執行
sh ./first.sh : 使用sh解釋執行


===========shell中的變數
變數定義:
class=gp1813

注意:
1、變數名不能使用數字開頭
2、=號的前後不能有空格
3、變數命令儘量不要使用關鍵字。(使用set或者help檢視)

變數賦值:
class=corder

只讀變數(不能再readonly之後重新賦值):
readonly class  

刪除變數:
unset class
直接把該行刪除

變數的取值:
$class  或者 ${class}   :{}可以限定變數名稱  
echo ${class}class,$classclass


變數型別:
區域性變數:某個指令碼或者是指令碼中某個方法中的變數
環境變數:配置到全域性環境變數配置檔案或者是個人的環境變數配置檔案中


字串:shell中一個弱型別的語言,變數都值的型別幾乎都是是字串。
字串拼接:
echo ${class}class

"" 、 '' 、`` 三者符號的區別:
"" : 雙引號中的取值符號或者是其它轉義符都能被識別
'' : 單引號中的所有的字串將會被原樣輸出
`` : 反引號中的內容是可執行的linux命令。反引號有的時候可以使用$(())來替代
echo "${class}class"
echo '${class}class'
echo `date`  : 該句和下一句是等價的
echo $(date)


獲取字串的長度:
echo "class variable length: "${#class}


字串的擷取:
echo ${class:2:3}  : 從2角標開始,擷取3個長度。角標從0開始


shell中的陣列:
和c中的陣列差不多一樣,暫不支援二維陣列,陣列下標都是從0開始。
陣列定義:
arr1=(1 2 3 4 5 6 9)
arr2=(
1
3
5
7
9
)
arr3[0]=2
arr3[2]=5
arr3[4]=666
 
陣列賦值:
arr1[0]=100
arr2[0]=1000
arr3[0]=10000

取單個值和所有值:
echo $arr1
echo $arr2
echo $arr3
echo ${arr2[*]},${arr2[@]}
echo ${arr3[4]} : 取單個值

取陣列的長度:
echo ${#arr3},${#arr3[*]},${arr3[100]}    當下標越界時不報異常


shell中的註釋:
除指令碼中的第一行#!/bin/bash等指定直譯器語句外的幾乎所有#都是註釋。
單行註釋:一個#
多行註釋:每一行加#或者使用方法封裝需要註釋的行,並且不呼叫該方法即可


shell中的運算:
數學運算
+ - * / %

#!/bin/bash
echo "$1+$2"=`expr $1 + $2`
echo "$1-$2"=`expr $1 - $2`
echo "$1*$2"=`expr $1 * $2`
echo "$1/$2"=`expr $1 / $2`
echo "$1%$2"=`expr $1 % $2`

echo "$1+$2"=$(($1+$2))
echo "$1-$2"=$(($1-$2))
echo "$1*$2"=$(($1*$2))
echo "$1/$2"=$(($1/$2))
echo "$1%$2"=$(($1%$2))

執行指令碼:
./math.sh 200 10

注意:
expr 是一個計算器工具命令,需要使用`` ,還需要注意空格
可以使用$(())來進行數學計算

關係運算
-eq -lt -le -ge -gt -ne = < <= >= > !=
 

#!/bin/bash
a=10
b=6
if [ $a -gt $b ]
then
echo "$a>$b"
fi
if [ $a -eq $b ]
then
echo "$a=$b"
fi
fi
if [ $a -le $b ]
then
echo "$a<=$b"
fi
if [ $a -ne $b ]
then
echo "$a!=$b"
fi

if (($a>$b))
then
echo "$a>$b"
fi


字元運算
=
!=
-z : 為0返回true,否則false
-n : 不為0返回true
str : 不為0返回true


file=/home/shell/math.sh
if [ -z $file ]
then
echo "$file is null"
else
echo "$file is not null"
fi

if [ -n $file ]
then
echo "$file is not null"
else
echo "$file is null"
fi

if [ $file ]
then
echo "$file is not null"
else
echo "$file is null"
fi

檔案運算:
-d: 是否是目錄
-f: 是否是檔案
-r:
-w:
-x:
-e: 檔案或者目錄是否存在
-s: 大小是否為0,不為0返回true
 


filepath=/home/shell/math.sh
if [ -f $filepath ]
then
echo "$filepath is file"
fi

if [ -e $filepath ]
then
echo "$filepath is exists"
fi

if [ -x $filepath ]
then
echo "$filepath is execute"
fi

if [ -s $filepath ]
then
echo "$filepath length is not 0"
fi

布林運算
!
-a : 邏輯與&&
-o : 邏輯或||

邏輯運算:&& ||   ,如果需要使用這種數學中的這種符號,需要使用雙中括號或者圓括號。

if [[ $1 -gt $2 || $1 -eq $2 ]]
then
echo "$1>=$2"
fi

if [[ $1 -gt $2 -o $1 -eq $2 ]]
then
echo "$1>=$2"
fi

三元運算子:
[條件] && cmd1 || cmd2   條件滿足,執行cmd1,不滿足cmd2

[ 1 = 1 ] && echo "1=1" || echo "1!=1"

控制條件:
if []
then
cmd1
fi


if []
then
cmd1
else
cmd2
fi


if []
then
cmd1
elif []
then
cmd2
else

fi


if [];then cmd1;fi   寫成一行

注意:
if後面需要有then
沒有elseif,只有elif
每一個if都需要有fi結束
每一個控制體中都必須要有語句
if和[]中的空格需要嚴格注意。如果使用$(())可以不用注意空格
else後面不能跟then,否則報錯

a=10
b=6
if [ $a -gt $b ]
then
echo "$a > $b"
elif [ $a -eq $b ]
then
echo "$a=$b"
else
echo "$a < $b"
fi

if(($a>$b))
then
echo "$a>$b"
fi

迴圈
for  while until
for i in 迴圈體
do
cmd...
done

for i in 1 2 3 ; do echo $i ; done
for i in `seq 1 10`
do
echo $i
done

basedir=/home/shell
for i in `ls $basedir`
do
echo $basedir/$i
done

while((迴圈體))
do
cmd...
done

i=0
while(($i<11))
do
echo $i
#i=`expr $i + 1`
let "i++"
done


i=0
while:  死迴圈
do
echo $i
#i=`expr $i + 1`
let "i++"
done
 

until 迴圈體
do
cmd...
done

echo "until==============="
j=0
until [ $j > 10 ]
do
echo $j
done

例子:取執行shell指令碼檔案後引數的時間,不管中間運算元有多少個,如果最後沒有時間,則輸出今天的時間

資料如形式如:

./for.sh -m fas -n 12 -d 2018-09-10
./for.sh -m fas -n 12 -d
./for -d 2018-09-10

date=
unitl [ $# -eq 0 ]
do
if [ $1'x' = '-dx' ]
then
shift
date=$1
fi
shift
done
echo $date

shell中支援case In模式匹配,類似switch case 
case 值 in
模式1)
cmd...
;;
模式2)
cmd...
;;
esac

shell中也支援continue和break

例子:

while:
do
echo "請輸入一個1-10的數字:"
read num
case $num in
1|2|3|4|5|6|7|8|9|10)
echo "你輸入的數字$num在1-10之間."
break
;;
*)
echo "你輸入的數字$num不在1-10之間.清繼續輸入:"
continue
;;
esac
done

shell中的方法
[function] 方法名(){
方法體
}


無引數無返回值方法:

function fun1(){
echo "i am in function fun1."
}

echo "before Function invoke."
fun1
echo "after Function invoke."


帶引數無返回值:

function fun2(){
echo "sum is:"$(($1+$2))
}
帶引數,帶返回值:

function fun3(){
echo "第1個引數:$1"
echo "第2個引數:$2"
echo "第9個引數:$9"
echo "第10個引數:$10"
echo "第10個引數:${10}"
echo "所有引數:$*"
echo "所有引數個數:$#"
return $(($1+$2))
}

$# :取引數的個數
$* : 取所有引數
[email protected] :取所有引數
$? : 取返回值.只能返回方法的退出程式碼(0-255之間)
$0 : 取運行當前指令碼
$1-9 : 取第幾個引數
${10} : 取第10個及以上的引數

$* 和 [email protected] 的區別:
不加""取值都一樣,可以將所有的值作為一個引數列表
加""取值時:
$* : 所有引數是一個字串,即一個元素"1 2 3"
[email protected] : 所有引數分別是多個字元,即可以做一個引數列表"1" "2" "3"


shell中的問價的引入:
source 檔案的絕對路徑
. 檔案的絕對路徑


shell中的除錯:
sh -n ./for.sh : 檢測for.sh語法是否有問題
sh -x ./for.sh : 檢視for.sh的執行詳細情況


sh -x ./for.sh : 按ctrl + z退出程式,然後分別按fg鍵(f鍵和g鍵)繼續除錯

斷點除錯:藉助第三方的除錯工具bashdb進行斷掉除錯

bashdb的命令:
l : 列出10行程式碼
n : 執行下語句
c 5: 一直執行n行
s 5: 單步執行多少次
b 5: 在5行打斷點
del 5 : 刪除5行的斷點
q : 退出
R : 重新斷點
finish : 直接完成