1. 程式人生 > 其它 >Shell指令碼結構與執行

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