1. 程式人生 > >shell程式設計入門(bash)

shell程式設計入門(bash)

一、背景知識

(1)什麼是shell?

高大上的解釋,往往讓人摸不住頭腦。一句話概括就是:shell程式設計就是對一堆Linux命令的邏輯化處理。

(2)為什麼需要shell?

譬如我們要在linux下建立一個檔案a.c,可以touch a.c 但是如果我現在是用在linux下建立100個檔案,分別為a1.c  a2.c.....a100.c 如果這時候還是手工去命令列下執行命令建立也可以,但是很累。最好的做法就是把建立過程寫成一個shell指令碼程式(for迴圈),然後去執行這個shell指令碼程式,執行這個程式的效果和手工在命令列輸入那些命令效果一樣的。

(3)如何執行shell(.sh)程式?

第一種:./xx.sh,和執行二進位制可執行程式方法一樣。這樣執行shell要求shell程式必須具有可執行許可權。chmod a+x xx.sh來新增可執行許可權。

第二種:source xx.sh,source是linux的一個命令,這個命令就是用來執行指令碼程式的。這樣執行不需要指令碼具有可執行許可權。

第三種:bash xx.sh,bash是一個指令碼程式直譯器,本質上是一個可執行程式。這樣執行相當於我們執行了bash程式,然後把xx.sh作為argv[1]傳給他執行。

(4)linux下常用的shell直譯器有哪些?

sh,bash,dash等.。

二、入門

(1)第一個程式

#!/bin/bash

echo "hello world."

shell中#符號表示註釋。shell的第一行比較特殊,一般都會以#!開始來指定使用的shell型別。在linux中,除了bash shell以外,還有很多版本的shell, 例如zsh、dash等等...不過bash shell還是我們使用最多的。

echo是linux中的輸出命令,該行的意思很明顯的就是輸出hello world!

(2)建立資料夾和檔案

#!/bin/bash
mkdir test
cd test
touch a.txt
cd ..

通過這個指令碼大家可以切實感受到shell程式設計就是linux命令的邏輯組合而已!!

三、變數和引用

(1)變數定義和初始化。

shell是弱型別語言(語言中的變數如果有明確的型別則屬於強型別語言;變數沒有明確型別就是弱型別語言),和C語言不同。在shell程式設計中定義變數不需要制定型別,也沒有型別這個概念。

(2)變數定義時可以初始化,使用=進行初始化賦值。在shell中賦值的=兩邊是不能有空格的

(3)變數賦值,變數定義後可以再次賦值,新的賦值會覆蓋老的賦值。shell中並不刻意區分變數的定義和賦值,反正每個變數就是一個符號,這個符號的值就是最後一個給他賦值時的值。

(4)變數引用。shell中引用一個變數必須使用$符號,$符號就是變數解引用符號。

注意:$符號後面跟一個字串,這個字串就會被當作變數去解析。如果這個字串本身沒有定義,執行時並不會報錯,而是把這個變數解析為空。也就是說在shell中沒有被定義的變數其實就相當於是一個定義並賦值為空的變數。

注意:變數引用的時候可以$var,也可以${var}。這兩種的區別是在某些情況下只能用${var}而不能簡單的$var

shell程式設計中分為兩種變數,第一種是我們自己定義的變數(自定義變數),第二種是Linux已定義的環境變數(環境變數, 例如:$PATH, $HOME 等..., 這類變數我們可以直接使用)。

程式例項:

#!/bin/bash

echo $PATH
#自定義變數hello
hello="hello world"
echo $hello

執行結果如下:

[email protected]:/mnt/hgfs/share/bash$ source var.sh 
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/work/tools/gcc-3.4.5-glibc-2.3.6/bin
hello world

注意:shell中無引號、單引號和雙引號的區別

(1)shell中使用字串可以不加雙引號,直接使用。而且有空格時也可以,但是缺陷是不能輸出"或者其他轉義字元。

(2)shell中也可以使用單引號來表示字串,也是直接使用的,不能輸出轉義字元

(3)單引號中:完全字面替換(不可包含單引號本身)

(4)雙引號中:

$加變數名可以取變數的值

反引號仍表示命令替換

\$表示$的字面值 輸出$符號

\`表示`的字面值

\"表示"的字面值

\\表示\的字面值

除以上情況之外,在其它字元前面的\無特殊含義,只表示字面值。

四、shell中呼叫linux命令

(1)直接執行

(2)反引號括起來執行。有時候我們在shell中呼叫linux命令是為了得到這個命令的返回值(結果值),這時候就適合用一對反引號(鍵盤上ESC按鍵下面的那個按鍵,和~在一個按鍵上)來呼叫執行命令。

程式例項:

#!/bin/bash

path=`pwd`
file=`ls`
echo "path = $path"
echo "file  = $file"

執行結果:

[email protected]:/mnt/hgfs/share/bash$ source cmd.sh 
path = /mnt/hgfs/share/bash
file  = 2.2.1.hello.sh
2.2.2.shell1.sh
2.2.4.shell2.sh
2.2.5.loop.sh
2.2.6.case.sh
2.2.8.Makefile
2.2.9
b.c
cmd.sh
test
var.sh

五、選擇分支

(1)if分支結構

讓我們先看一下MAN手冊是怎麼介紹if命令的:

可以看出,if後面跟著的是一個命令,而不是像其他語言那樣返回布林值(true,false)的表示式。通過MAN手冊的介紹我們可以知道:在shell指令碼的if其實是根據緊跟後面的那個命令的退出狀態碼來判斷是否執行then後面的語句的。

關於退出狀態碼,你只需要記住:正常退出(命令執行正常)的狀態碼是0, 非正常退出的狀態碼不是0(有不少)。

以上語句的語義為: 如果if後面的命令執行正常(狀態碼0),那麼就執行then後面的語句。否則不執行。 fi代表if語句的結束。

例如:

  
  1 #!/bin/bash
  #這兒由於pwd是linux內建的命令,因此執行後會正常退出(狀態碼0),所以會執行then中的語句
  #如果此處替換為一個不存在的命令(例如: pw),那麼就會非正常退出,不會執行then中的語句
  2 
  3 if pwd
  4 then
  5     echo "OK"
  6 else
  7     echo "error"
  8 fi

程式最終輸出OK

那麼你可能會問了,我要是就是想像C語言那樣判斷一個表示式是否成立怎麼辦呢?客官彆著急,有以下兩種解決辦法:

(1)使用test命令

test EXPRESSION ,test後面跟著的是一個表示式,如果表示式成立,就會退出並返回退出狀態碼0,否則返回非0。這樣,我們就可以藉助test命令來實現if對錶達式的判斷了。一個典型的格式如下:

if  test expression
then
    commands
else 
    commands    
fi

表示式成立就執行then語句,否則else語句。值得注意的是:

test命令只能判斷一下三類條件:

  • 數值比較
  • 字串比較
  • 檔案比較
     

數值比較

(-eq)、大於(-gt)、小於(-lt)、大於等於(-ge)、小於等於(-le)

例如:

  1 #!/bin/bash
  2 
  3 num1=10
  4 num2=20
  5 
  6 if test $num1 -gt $num2
  7 then
  8     echo "num1>num2"
  9 else
 10     echo "num1<=num2"
 11 fi
 12 

執行結果:

num1<=num2

 

字串比較

注意:這個測試相等只有一個等號

例如:

  1 #!/bib/bash
  2 
  3 str1=test
  4 str2=test
  5 
  6 if test $str1 = $str2
  7 then
  8     echo equal
  9 else
 10     echo "not equal"
 11 fi
 12 

輸出結果:

equal

檔案比較

檔案比較的命令很多,大家可以檢視man手冊來進行學習,常用的就是 -f ,即判斷檔案是否存在

(2)使用雙括號和雙方括號

  • 使用雙括號

可以看到使用test命令判斷數字邏輯的時候必須符合其命令的規範,需要用到-gt、-eq等,可不可以直接像C語言那樣呢?答案是可以的,我們只需要在表示式外邊加雙括號,但是值得注意的是:括號裡面兩邊都需要有空格,而且(())中變數是可以不使用$來引用的

雙括號命令允許你在比較過程中使用高階數學表示式。關鍵是使用雙括號,咱就可以用數學比較符號啦(等於==, 大於>, 小於< 等等都能使用啦)

例1:

  1 #!/bin/bash
  2 
  3 num1=10
  4 num2=20
  5 
  6 if (( num1 == num2 ))
  7 then
  8     echo "num1==num2"
  9 else
 10     echo "num1!=num2"
 11 fi
 12 

輸出num1!=num2

例2:

  1 #!/bin/bash
  2 
  3 num1=10
  4 num2=10
  5 
  6 if (( $num1 == $num2 ))
  7 then
  8     echo "num1==num2"
  9 else
 10     echo "num1!=num2"
 11 fi
 12 

輸出num1=num2

  • 使用雙方括號

雙方括號命令提供了針對字串比較的高階特性。它不僅解決了使用test所帶來的一系列毛病,還提供了一些test命令所沒有的高階用法。測試相等同樣可以使用==。

例1:

  1 #!/bib/bash
  2 
  3 str1=haha
  4 str2=haha
  5 
  6 if [[ $str1 = $str2 ]]
  7 then
  8     echo equal
  9 else
 10     echo "not equal"
 11 fi
 12 

輸出equal

例2:

  1 #!/bib/bash
  2 
  3 str1=haha
  4 str2=hahe
  5 
  6 if [[ $str1 = $str2 ]]
  7 then
  8     echo equal
  9 else
 10     echo "not equal"
 11 fi
 12 

輸出:not equal

補充:

if判斷式中使用“-o”表示邏輯或,“-a”表示邏輯與

相當於C語言中在if後面的條件式中用邏輯與、邏輯或來連線2個式子,最終的if中是否成立取決於2個式子的邏輯運算結果。

 

(2)case結構

可以用case語句匹配一個值與一個模式,如果匹配成功,執行相匹配的命令。case語句格式如下:

case 值 in
模式1)
    command1
    command2
    ...
    commandN
    ;;
模式2)
    command1
    command2
    ...
    commandN
    ;;
*)
    command1
    command2
    ...
    commandN
    ;;
esac

case工作方式如上所示。取值後面必須為單詞in,每一模式必須以右括號結束。取值可以為變數或常數。匹配發現取值符合某一模式後,其間所有命令開始執行直至 ;;。

取值將檢測匹配的每一個模式。一旦模式匹配,則執行完匹配模式相應命令後不再繼續其他模式。如果無一匹配模式,使用星號 * 捕獲該值,再執行後面的命令。

例項:

  1 #!/bin/bash
  2 num=2
  3 case $num in
  4 1)
  5     echo "num=1";;
  6 2)
  7     echo "num=2";;
  8 3)
  9     echo "num=3";;
 10 4)
 11     echo "num=4";;
 12 *)
 13     echo "defaul";;
 14 esac  

輸出:

num=2

 

 

 

 

Ref:

https://www.cnblogs.com/dongying/p/6262935.html

https://blog.csdn.net/a5nan/article/details/53079591