Shell指令碼結構與執行
1.shell指令碼結構與執行
1.1 指令碼結構
[root@localhost ~]# mkdir shell
[root@localhost ~]# cd shell
[root@localhost shell]# vi 1.sh //寫入如下內容
#!/bin/bash
touch /tmp/1.txt
chmod 600 /tmp/2.txt
mv /tmp/1.txt /tmp/2.txt
1.2 指令碼執行
[root@localhost shell]# bash 1.sh
shell指令碼還有一種執行方法,但前提是指令碼本身要有執行許可權,所以在執行前我們需要給指令碼加一個x許可權
[root@localhost shell]# chmod +x 1.sh //賦予許可權
[root@localhost shell]# ./1.sh //執行指令碼
2常用命令
2.1檢視指令碼執行過程
[root@localhost shell]# bash -x 1.sh
2.2 檢視指令碼是否有語法錯誤
[root@localhost shell]# bash -n 1.sh
2.3 date 命令
date +%Y-%m-%d #年(以四位數字格式列印年份)月日
date +%y-%m-%d #年(以兩位數字格式列印年份)月日
date +%T #小時分鐘秒
date +%H:%M:%S #小時分鐘秒
date +%w #一週中的第幾天
date +%W #一年中的第幾周
使用命令date +%s 顯示從 1970 年 1 月 1 日 00:00:00 UTC 到目前為止的秒數。
使用命令 date -d @1647832130顯示輸入秒數之前的時間
date -d "+1 hour" #一個小時後
date -d "-1 hour" #一個小時前
date -d "+1day" #一天後
date -d "-1 day" #一天前
3.shell指令碼中的變數
在shell指令碼中使用變數可以節省時間並且使我們的指令碼更加專業,所以當我們編寫一個指令碼時,就可以使用變數來代替某個使用頻繁並且長度很長的字串。變數的格式:“變數名=變數的值”。
3.1 引用命令的結果
當我們引用某個命令的結果時,可以使用變數代替
[root@localhost ~]# a= date +%w
#將命令結果賦值給變數
[root@localhost ~]# echo $a
[root@localhost ~]# a=$(date +%w) #將命令結果賦值給變數
[root@localhost ~]# echo $a
3.2 與使用者互動
[root@localhost ~]# read -p "請輸入一個數字:" n
請輸入一個數字:10
[root@localhost ~]# echo $n
10
[root@localhost ~]# read -p "請輸入一個數字:"
請輸入一個數字:100
[root@localhost ~]# echo $REPLY
100
3.3 內建變數
[root@localhost shell]# vi bian.sh #建立一個名為bian.sh的指令碼
[root@localhost shell]# cat bian.sh
#!/bin/bash
echo "$1=$1"
echo "第二個引數是$2"
echo "第三個引數是$3"
echo "本指令碼一共有$#個引數"
echo "$0是$0"
[root@localhost shell]# sh bian.sh #執行指令碼
$1=
第二個引數是
第三個引數是
本指令碼一共有0個引數
$0是bian.sh
[root@localhost shell]# sh bian.sh a b #再次執行指令碼
$1=a
第二個引數是b
第三個引數是
本指令碼一共有2個引數
$0是bian.sh # $0就是指令碼的名字
3.4 數學運算
shell指令碼中的變數常用於數學運算當中,示例如下:
[root@localhost shell]# vi sum.sh #建立一個名為sum.sh的指令碼
[root@localhost shell]# cat sum.sh
#!/bin/bash
a=1
b=2
sum=a+((b))這種寫法
echo "b=$sum"
[root@localhost shell]# sh sum.sh #執行指令碼
1+2=3
4.shell中的邏輯判斷
4.1 不帶有else
基礎結構:
if 判斷語句; then
command
fi
示例如下:
[root@localhost shell]# vi if1.sh
[root@localhost shell]# cat if1.sh
#!/bin/bash
a=10
if [ $a -gt 4 ]
then
echo ok
fi
[root@localhost shell]# sh -x if1.sh #執行指令碼
+ a=10
+ '[' 10 -gt 4 ']'
+ echo ok
ok
[root@localhost shell]# sh -n if1.sh
4.2 帶有else
基礎結構:
if 判斷語句 ; then
command
else
command
fi
示例如下:
[root@localhost shell]# vi if2.sh
[root@localhost shell]# cat if2.sh
#!/bin/bash
a=10
if [ $a -gt 4 ]
then
echo ok
else
echo "not ok"
fi
[root@localhost shell]# sh -x if2.sh #執行指令碼
+ a=10
+ '[' 10 -gt 4 ']'
+ echo ok
ok
4.3 帶有elif
示例如下:
[root@localhost shell]# vi if3.sh
[root@localhost shell]# cat if3.sh
#!/bin/bash
a=3
if [ $a -gt 4 ]
then
echo ok
elif [ $a -gt 8 ]
then
echo "very ok"
else
echo "not ok"
fi
[root@localhost shell]# sh -x if3.sh #執行指令碼
+ a=3
+ '[' 3 -gt 4 ']'
+ '[' 3 -gt 8 ']'
+ echo 'not ok'
not ok
4.4 巢狀
示例如下:
[root@localhost shell]# vi if4.sh
[root@localhost shell]# cat if4.sh
#!/bin/bash
a=10
if [ $a -gt 4 ]
then
if [ $a -lt 20 ]
then
echo "ok"
else
echo "very ok"
fi
else
echo "not ok"
fi
[root@localhost shell]# sh -x if4.sh #執行指令碼
+ a=10
+ '[' 10 -gt 4 ']'
+ '[' 10 -lt 20 ']'
+ echo ok
ok
4.5 多個條件
if [ $a -gt 5 ] && [ $a -lt 10 ] == if [ $a -gt 5 -a $a -lt 10] # -a表示 and
if [ $b -gt 5 ] || [ $b -lt 3] == if [ $b -gt 5 -o $b -lt 3 ] # -o表示 or
4.6 if邏輯判斷
if判斷檔案的目錄屬性
shell指令碼中if經常用於判斷文件的屬性,比如判斷是普通檔案還是目錄,判斷檔案是否有讀、寫、執行許可權等。If常用選項如下:
-e:判斷檔案或目錄是否存在。
-d:判斷是不是目錄以及是否存在。
-f:判斷是不是普通檔案以及是否存在。
-T:判斷是否有讀許可權。
-w:判斷是否有寫許可權。
-X:判斷是否可執行。
4.7 shell中的case判斷
case判斷的基礎格式如下:
case 變數 in
value1) #不限制value的個數
command
;;
value2)
command
;;
) #此處代表其他值
command
;;
esac
為了讓我們能夠更加 清晰的理解case邏輯判斷,接下來我們編寫一個指令碼來進行實驗
[root@localhost shell]# vi case.sh
#!/bin/bash
read -p "Please input a number:" n
if [ -z "$n" ]
then
echo "Please input a number."
exit 1
fi
n1=echo $n|sed 's/[0-9]//g'
if [ -n "$n1" ]
then
echo "Please input a number."
exit 1
fi
if [ $n -lt 60 ] && [ $n -ge 0 ]
then
tag=1
elif [ $n -ge 60 ] && [ $n -lt 80 ]
then
tag=2
elif [ $n -ge 80 ] && [ $n -lt 90 ]
then
tag=3
elif [ $n -ge 90 ] && [ $n -le 100 ]
then
tag=4
else
tag=0
fi
case $tag in
echo "not ok"
;;
echo "ok"
;;
echo "very ok"
;;
echo "oook"
;;
*)
echo "The number range is 0-100."
;;
esac
執行結果;
[root@localhost shell]# sh case.sh Please input a number:1 not ok [root@localhost shell]# sh case.sh Please input a number:81 very ok [root@localhost shell]# sh case.sh Please input a number:66 ok [root@localhost shell]# sh case.sh Please input a number:100 oook
5.shell中的迴圈
5.1 for迴圈
基礎結構如下:
for 變數名 in 迴圈條件;
do
command
done
下面進行一個簡單的實驗演示,演示如下;
[root@localhost shell]# vi for1.sh
#!/bin/bash
sum=0
for i in seq 1 10
do
sum=sum+$i]
echo $i
done
echo $sum
執行結果;
[root@localhost shell]# sh for1.sh 1 2 3 4 5 6 7 8 9 10 55
5.2 while迴圈
基礎結構:
while 條件;do
command
done
示例1;
[root@localhost shell]# vi while1.sh #!/bin/bash while : #此處冒號表示死迴圈 do load=`w|head -1|awk -F 'load average:' '{print $2}'|cut -d. -f1` #賦值給變數load if [ $load -gt 10 ] then top|mail-s "load is high: $load" asldkfls011.com fi sleep 30 done
執行結果;
[root@localhost shell]# sh -x while1.sh + : ++ w ++ head -1 ++ awk -F 'load average:' '{print $2}' ++ cut -d. -f1 + load=' 0' + '[' 0 -gt 10 ']' + sleep 30
示例2;
[root@localhost shell]# vim while2.sh #!/bin/bash while : do read -p "Please input a number: " n if [ -z "$n" ] then echo "you need input sth." continue fi n1=`echo $n|sed 's/[0-9]//g '` if [ -n "$n1" ] then echo "you just only input numbers." continue fi break done echo $n
執行結果;
[root@localhost shell]# sh while2.sh Please input a number: q you just only input numbers. Please input a number: 1 1 [root@localhost shell]# sh while2.sh Please input a number: 2 2 [root@localhost shell]# sh while2.sh Please input a number: 4444551 4444551
6.shell中的中斷與繼續
6.1 跳出迴圈
break 在指令碼中表示跳出該層迴圈,示例如下
[root@localhost shell]# vim break1.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i -eq 3 ] then break fi echo $i done echo aababab
執行結果;
[root@localhost shell]# sh break1.sh 1 1 2 2 3 aababab
6.2 結束本次迴圈
當在shell指令碼中使用continue時,結束的不是整個迴圈,而是本次迴圈。忽略continue之下的程式碼,直接進行下一次迴圈。
[root@localhost shell]#vi continue1.sh #建立一個shell指令碼 #!/bin/bash for i in `seq 1 5 ` do echo $i if [ $i == 3 ] then continue #此處continue表示若 $i == 3 則結束本次迴圈 fi echo $i done echo $i
執行結果;
[root@localhost shell]# sh continue1.sh 1 1 2 2 3 4 4 5 5 5
6.3 退出整個指令碼
當我們在shell指令碼中遇到exit時,其表示直接退出整個shell指令碼。
[root@localhost shell]# vi exit1.sh #!/bin/bash for i in `seq 1 5` do echo $i if [ $i == 3 ] then exit fi echo $i done echo aaaa
執行結果;
[root@localhost shell]# sh -x exit1.sh ++ seq 1 5 + for i in '`seq 1 5`' + echo 1 1 + '[' 1 == 3 ']' + echo 1 1 + for i in '`seq 1 5`' + echo 2 2 + '[' 2 == 3 ']' + echo 2 2 + for i in '`seq 1 5`' + echo 3 3 + '[' 3 == 3 ']' + exit
7.shell中的函式
shell指令碼中的函式就是先把一段程式碼整理到了一個小單元中,並給這個小單元命名,當我們用到這段程式碼時直接呼叫這個小單元的名字就可以了,這樣很方便,省時省力。但我們需要注意,在shell指令碼中,函式一定要寫在前面,因為函式要被呼叫的,如果還未出現就被呼叫就會出錯。
基礎格式;
function f_name() { command }
7.1 打印出第一個,第二個引數,引數的個數及指令碼名
[root@localhost shell]# vi fun1.sh #/bin/bash input() { echo $1 $2 $# $0 # 函式的引數:$1 $2 $# ;$0則是指令碼的名字 } input 1 a b
執行結果;
[root@localhost shell]# sh fun1.sh 1 a 3 fun1.sh [root@localhost shell]# sh -x fun1.sh + input 1 a b + echo 1 a 3 fun1.sh 1 a 3 fun1.sh
7.2 加法的函式
[root@localhost shell]# vi fun2.sh #!/bin/bash sum() { s=$[$1+$2] echo $s } sum 1 2
執行結果;
[root@localhost shell]# sh -x fun2.sh + sum 1 2 + s=3 + echo 3 3
7.3 獲得一個網絡卡的IP地址
[root@localhost shell]# vi fun3.sh #!/bin/bash ip() { ifconfig |grep -A1 "$1: " |tail -1 |awk '{print $2}' } read -p "Please input the eth name: " e myip=`ip $e` echo "$e address is $myip"
執行結果;
[root@localhost shell]# sh fun3.sh Please input the eth name: eth0 eth0 address is 192.168.174.15 [root@localhost shell]# sh fun3.sh Please input the eth name: lo lo address is 127.0.0.1
8. shell中的陣列
8.1 陣列讀取
首先我們需要先定義一個數組a=(1 2 3 4 5);
命令 echo ${a[@]}讀取陣列中的全部元素。
[root@localhost shell]# a=(1 2 3 4 5 6 7 8) [root@localhost shell]# echo ${a[@]} 1 2 3 4 5 6 7 8
命令 echo ${#a[@]} 獲取陣列的元素個數。
[root@localhost shell]# echo ${#a[@]} 8
命令 echo ${a[2]} 讀取第三個元素,陣列從0開始。
[root@localhost shell]# echo ${a[2]} 3
echo ${a[*]} 等同於 ${a[@]} 作用為顯示整個陣列。
[root@localhost shell]# echo ${a[*]} 1 2 3 4 5 6 7 8
8.2 陣列賦值
a[1]=100; echo ${a[@]} 替換指定的元素值。
[root@localhost shell]# a[1]=100 [root@localhost shell]# echo ${a[@]} 1 100 3 4 5 6 7 8
a[5]=2; echo ${a[@]} 如果下標不存在則會自動新增一個元素
[root@localhost shell]# a[5]=2 [root@localhost shell]# echo ${a[*]} 1 100 3 4 5 2 7 8
a[7]=6; echo ${a[@]} 跳著新增元素時,中間未賦值的元素,不顯示且無值。
[root@localhost shell]# a[7]=6 [root@localhost shell]# echo ${a[@]} 1 100 3 4 5 2 7 6
8.3 陣列的刪除
命令unset a[1] 用於刪除單個元素。
[root@localhost shell]# echo ${a[@]} 1 3 4 5 2 7 6 6 [root@localhost shell]# echo ${a[7]} 6 [root@localhost shell]# unset a[7] [root@localhost shell]# echo ${a[@]} 1 3 4 5 2 7 6
命令unset a 用於刪除整個陣列。
[root@localhost shell]# echo ${a[@]} 1 3 4 5 2 7 6 [root@localhost shell]# unset a [root@localhost shell]# echo ${a[@]}
8.4 陣列分片
在進行實驗操作之前,需要對一個數組進行賦值 a=(seq 1 5
) 。
命令echo ${a[@]:0:3} 表示從第一個元素開始,擷取3個元素,並打印出來。
[root@localhost shell]# a=(`seq 1 5 `) [root@localhost shell]# echo ${a[*]} 1 2 3 4 5 [root@localhost shell]# echo ${a[@]:0:3} 1 2 3
命令echo ${a[@]:1:4} 表示從第二個元素開始,擷取4個元素
[root@localhost shell]# echo ${a[@]:1:4} 2 3 4 5
echo ${a[@]:0-3:2} 表示從倒數第3個元素開始,擷取2個元素
[root@localhost shell]# echo ${a[@]:0-3:2} 3 4 [root@localhost shell]# echo ${a[@]:0-1:2} 5 [root@localhost shell]# echo ${a[@]:0-2:2} 4 5
8.5 陣列替換
使用命令echo ${a[@]/b/100} 表示用100替換b,但不會儲存替換
[root@localhost shell]# a=(a b c d e) [root@localhost shell]# echo ${a[*]} a b c d e [root@localhost shell]# echo ${a[@]/b/100} a 100 c d e
使用命令a=(${a[@]/b/100}) 表示用100替換b,這種方法不僅可以打印出來還可以儲存替換
[root@localhost shell]# a=(${a[@]/b/100}) [root@localhost shell]# echo ${a[*]} a 100 c d e