shell編程基礎

shell概述linux

1. shell編程的意義git

我的理解,shell編程相似於存儲過程。存儲過程是完成指定功能的一組sql語句集合,而shell編程就是完成指定功能的一組linux命令的集合。例如,咱們要在服務器上部署一個一個項目,一般要作以下幾個操做:sql

  • 進入項目目錄:cd /home/dubhlinn/project/demo
  • 切分支:git checkout master
  • 從遠程倉庫拉取最新代碼:git pull
  • 打包:mvn clean install -P production
  • 部署:docker build -t ...

每次部署都要執行相同的一套流程,若是能把這些操做放在一個文件裏,只需執行這個文件便可,會明顯提升服務器運維管理的效率。這就是shell編程要知足的需求。docker

2. shell分類shell

linux的shell分類不少,例如編程

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh)

其中,最經常使用的是bash shell,即/bin/bash。vim

3. shell編程的格式bash

可使用vi或vim編輯器建立shell腳本文件,其擴展名並無要求,可使用(.sh)表示它是一個shell文件,例如hello.sh、deploy.sh等,可是使用別的擴展名或者不用擴展名也不影響其執行。shell文件的第一行通常要指定shell種類,#!用來告訴系統,這個文件使用哪一個解釋器。例如最經常使用的bash shell這樣寫:服務器

#!/bin/bash
#這是單行註釋
echo "hello world"
:<<!
這是多行註釋
這是多行註釋
這是多行註釋
!
echo "byebye"

 

 4. shell腳本的執行方式運維

若是給shell腳本賦予了可執行權限,則直接寫文件的路徑名便可執行,可使用絕對路徑或相對路徑,注意若是shell文件正好在當前目錄下,相對路徑要以 ./ 開頭,而不能直接寫文件名。若是並無給shell腳本賦予可執行權限,則須要在文件路徑名前加 sh。通常推薦第一種,即賦予用戶對文件的可執行權限。例如,在當前路徑(/home/dubhlinn)下有一個hello.sh的腳本,

(1) 當用戶對其有可執行權限時:

./hello.sh

/home/dubhlinn/hello.sh

(2) 當用戶對其無可執行權限時:

sh ./hello.sh

sh /home/dubhlinn/hello.sh

 

shell編程的變量

1. 變量的定義

變量名 = 變量值

#輸出環境變量
echo $HOME echo $USER #自定義變量
A=12 B=hello echo A=$A echo B=$B

shell編程中變量分爲兩類:環境變量、自定義變量。環境變量是linux系統已經預先定義好的變量,能夠直接使用;自定義變量必須先定義,再使用。定義變量的的語法很簡單,可是有幾點須要注意:

  • 變量名能夠由數字、字母、下劃線組成,可是不能以數字開頭
  • 定義變量時,等號兩側不容許使用空格,這一點跟Java、JavScript等語言有區別
  • 變量名習慣用大寫字母表示
  • 定義變量時不用美圓符號($),使用變量時要使用美圓符號($)
  • 變量被定義後,能夠從新賦值,後面的值會覆蓋前面

2. 聲明環境變量

(1) export 變量名=變量值

(2) source 文件路徑名

第一步跟自定義變量相比,只是多了一個export關鍵字,第二步是爲了讓shell文件生效。完成這兩步以後,能夠在其它的shelle文件或中獲取剛剛聲明的環境變量。而相比之下,自定義變量僅限於在一個shell文件中使用,在其餘的shell文件中沒法使用。

#設置環境變量
export VILLA=Spain7 export TORRES=Spain9 

須要注意的是,在一個shell文件中,自定義變量會覆蓋同名的環境變量,例如

#輸出環境變量
echo VILLA=$VILLA #自定義變量
VILLA=Bacelona7 #輸出,看是環境變量仍是自定義變量
echo VILLA=$VILLA

第一次輸出的是環境變量的值:Spain7,第二次輸出的是自定義變量的值:Bacelona7。

3. 變量的撤銷

unset 變量名

#撤銷變量
B=hello unset B echo B=$B

4. 靜態變量,不能被撤銷

readonly 變量名=變量值

:<<! 靜態變量 不能撤銷 ! readonly C=5 echo C=$C unset C echo C=$C

執行這個腳本會報錯,由於C是靜態變量,不能使用unset將其撤銷。

5. 將linux命令的執行結果賦給變量

變量名=`命令`    或    變量名=$(命令)

#將linux命令的執行結果賦給變量,兩種方式等價
A=`ls -lh` B=$(date) echo A=$A echo B=$B

6. 接收參數

在shell腳本中能夠像Java方法同樣接收形參,其語法格式以下

  • $數字  表示第幾個參數,超過10的須要用${數字},例如$一、$二、${15}
  • $*      表示全部參數,且做爲一個總體
  • $@     表示全部參數,但每一個分別對待
  • $#      表示參數的個數
#輸出單個參數
echo 第1個參數爲$1 echo 第2個參數爲$2 echo 第10個參數爲${10} #輸出所有參數,且做爲一個總體
echo 所有參數爲$*

#輸出所有參數,且分別對待
echo 參數分別爲$@ #輸出參數個數
echo 總共有$#個參數

在執行這個shell腳本時,能夠傳入參數,例如 ./hello.sh 1 2 3

 

shell編程的運算符

shell的運算符自己跟Java、JavaScript等語言基本同樣:+、-、*、/、%等,但實際應用有一些獨特的規則,主要有如下三種使用方法

  • $((運算式))
  • $[運算式]
  • expr 運算式

其中,前兩種方式的運算符之間不能加空格,第三種方式的運算符之間必須加空格,並且括號、乘號須要加轉義符號,即 \(、\)、\* 。這些規則看起來有點奇怪,下面用幾個具體的示例來講明。

1. 求 (3+5)*4/(2+1)的值

#使用第一種方式計算
R1=$(((3+5)*4/(9-1))) echo R1=$R1 #使用第二種方式計算
R2=$[(3+5)*4/(9-1)] echo R2=$R2 #使用第三種方式計算
R3=`expr \( 3 + 5 \) \* 4 / \( 9 - 1 \)` echo R3=$R3 

2. 求第一個參數和第二個參數的和,而後取除以第三個參數的餘數

#使用第一種方法計算
R1=$((($1+$2)%$3)) echo R1=$R1 #使用第二種方法計算
R2=$[($1+$2)%$3] echo R2=$R2 #使用第三種方法計算
R3=`expr \( $1 + $2 \) % $3` echo R3=$R3

 

shell編程的條件分支語句

1. if條件分支語句

if [ 條件1 ]

  then

    語句1

elif [ 條件2 ]

  then

    語句2

else

    語句3

fi

其中,中括號與條件之間必須加空格。

符號 意義
= 兩個字符串是否相等
-lt 小於
-le 小於等於
-eq 等於
-ge 大於等於
-gt 大於
-ne 不等於
-r 文件或目錄有讀的權限
-w 文件或目錄有寫的權限
-x 文件或目錄有執行權限
-f 文件存在而且是一個常規文件
-e 文件存在
-d 文件存在而且是一個目錄

2. case條件分支語句

case 變量 in

值1)

語句1

;;

值2)

語句2

;;

*)

語句3

;;

esac 

 

3. 應用示例

#判斷文件是否存在
if [ -e /home/dubhlinn/shell/aaa.txt ] then echo 存在 else echo 不存在 fi #判斷是否是一個目錄
if [ -d /home/dubhlinn/shell ] then echo 是一個目錄 else echo 不是一個目錄 fi #判斷文件是否有可執行權限
if [ -x /home/dubhlinn/shell/hello.sh ] then echo 有可執行權限 else echo 無可執行權限 fi #判斷兩個數字的大小
if [ $[5*3] -ge $[6+7] ] then echo 前者大於等於後者 else echo 前者小於後者 fi #判斷傳入的參數範圍
if [ $1 -gt 90 ] then echo 優秀 elif [ $1 -ge 60 ] then echo 及格 else echo 不及格 fi
#!/bin/bash

:<<! 若是參數是6,則輸出"星期六", 若是參數是7,則輸出"星期日" 若是是其餘,則輸出"工做日" 用兩種判斷語句實現 !


#使用if語句實現
if [ $1 -eq 6 ] then echo 星期六 elif [ $1 -eq 7 ] then echo 星期日 else echo 工做日 fi #使用case語句實現
case $1 in
6) echo 星期六 ;; 7) echo 星期日 ;; *) echo 工做日 ;; esac

 

 shell編程的循環語句

1. for循環

for ((初始值;循環條件;變量變化))

do

    表達式

done

2. while循環

while [ 條件 ]

do

    表達式

    變量變化

done

注意,中括號跟條件之間須要加空格。

3. 使用示例

#!/bin/bash
 :<<! 分別使用for循環和while循環 計算從1到控制檯參數的累加之和 例如,控制檯輸入100,則計算從1-100之和 ! #使用for循環
SUM1=0 for ((i=0;i<=$1;i++)) do SUM1=$[$SUM1+$i] done echo SUM1=$SUM1 #使用while循環
SUM2=0 j=1
while [ $j -le $2 ] do SUM2=$[$SUM2+j] j=$[$j+1] done echo SUM2=$SUM2

 

控制檯交互

1. read關鍵字

read [-p 提示信息] [-t 等待時間] 參數

其中,-p後面接提示信息,顯示在控制檯;-t後面接等待時間(單位是秒),超過這個時間沒有響應則自動退出;參數是用來接收用戶在控制檯輸入的值的變量名。

2. 使用示例

#/bin/bash

#提示用戶輸入一個數字,而後打印到控制檯
read -p "請輸入一個數字" A echo 您輸入的數字是: $A #提示用戶輸入一個數字,而後打印到控制檯,最多等待5秒
read -p "請在5秒鐘以內輸入一個不等於零的數" -t 5 B if [ $B -ne 0 ] then echo 您輸入的數字是:$B else echo 輸入無效 fi

 

shell函數

shell編程跟其餘編程語言同樣,也有函數(Java中叫方法)。shell函數分爲系統函數和自定義函數,跟變量同樣,系統函數是linux系統已經定義好的,咱們能夠直接拿來用;自定義函數須要本身先定義,再調用。

1. basename函數

basename 全路徑 [後綴]

basename是一個系統函數,用於返回文件名,即最後一個/後面的部分,若是加了中括號內的後綴,表示連後綴也去掉。例如

#!/bin/bash

#返回一個全路徑的文件名
basename /home/dubhlinn/shell/aaa.sh #返回一個全路徑的文件名,去掉後綴
basename /home/dubhlinn/shell/aaa.sh .sh

2. dirname函數

dirname 全路徑

dirname也是一個系統函數,它與basename正好相反,返回的是目錄名,即最後一個/以前的部分。

#!/bin/bash

#返回一個全路徑的目錄名
dirname /home/dubhlinn/shell/aaa.sh

3. 自定義函數的定義格式

function 函數名() {

    語句;

    [return 返回值;]

}

4. 自定義函數的調用格式

函數名 參數

5. 自定義函數使用示例

#!/bin/bash
 :<<! 定義一個函數,求兩個參數之和 ! #定義函數
function getSum() { SUM=$[$A+$B] echo 函數調用結構爲$SUM } #調用函數
A=5 B=6 getSum $A $B
相關文章
相關標籤/搜索