1. 程式人生 > >shell指令碼學習手冊

shell指令碼學習手冊

簡介:

Shell 是一個用C語言編寫的程式,它是使用者使用Linux的橋樑。Shell既是一種命令語言,又是一種程式設計語言。

Shell 是指一種應用程式,這個應用程式提供了一個介面,使用者通過這個介面訪問作業系統核心的服務。

Ken Thompson的sh是第一種Unix Shell,Windows Explorer是一個典型的圖形介面Shell。

Shell教程入門

1、shell指令碼

shell指令碼shell script,是一種為shell而編寫的指令碼程式。然而通常所說的shell卻是指shell指令碼,而非shell本身。

Linux系統shell種類眾多,常用的有

shbash

2、shell指令碼實踐

shell指令碼用#!/bin/bash#!/bin/sh之類的方式,制定執行指令碼的shell,#!是識別符號。

  1. #!/bin/sh
  2. echo "Hello World"

執行shell指令碼的兩種方法:

  • 作為可執行程式

將shell文字儲存為.sh格式檔案,賦予執行許可權

    1. chmod + x ./test.sh # 賦予可執行許可權
    2. ./test.sh #執行指令碼,注意此處需要指明當前目錄下的test.sh哦,不然會去path路徑找的,呵呵。
  • 作為解釋其引數

直接解釋執行,如此就不用寫#!/bin/sh之類的引用註釋了。

    1. /bin/sh test.sh
    2.  
    3. # 類似java、php、python指令碼
    4.  
    5. /bin/php test.php

Shell變數

變數命名語法,不需要$符號,php需要。命名要求:

  • 首字母必須字母a-z或A-Z
  • 不能空格,可用_
  • 不能標點
  • 不能使用bash關鍵字
  1. #注意,不同於其他程式語言,等號之間不要有空格。
  2. your_variable=
    "your,name"
  1. # 使用語句給變數賦值,如下迴圈顯示出/etc目錄下的檔名
  2. for file in 'ls /etc'

1、使用變數

使用已定義變數,只需在變數前加$符號即可:

  1. your_variable='yourname'
  2. echo $your_variable
  3. echo $(your_variable)

變數名可以加{}來標識變數名的範圍,如:

  1. for skill in Ada Coffe Action Java; do
  2.     echo "I am good at ${skill}Script"
  3. done

如果不加{}skill就可能被認為skillScript而導致變數找不到

已定義的變數可重新定義:

  1. your_name="tom"
  2. echo $your_name
  3. your_name="john"
  4. echo $your_name

2、只讀變數

使用readonly命令將變數只讀,則不可再改變,否則報錯。

  1. #!/bin/bash
  2. myUrl="http://www.w3cschool.cc"
  3. readonly myUrl
  4. myUrl="new url" #此處就會報錯,因為變數只讀了。

3、刪除變數

使用unset命令刪除變數:

unset variable_name

==刪除變數後不能再用,而unset不能刪除只讀變數==

  1. #!/bin/sh
  2. myUrl="http://www.google.com"
  3. unset myUrl
  4. echo $myUrl #此時輸出就沒接過了,因為變數被刪除了。

4、變數型別

執行shell時,會同時存在三種變數:

  • 區域性變數:指令碼中定義的變數,僅作用於本shell指令碼內。
  • 環境變數:所有程式,包括shell啟動程式都能訪問的環境變數。
  • shell變數:shell程式的特殊變數。

5、shell字串

shell常用numberstring,其中string可以單引號、雙引號或者不用引號。但是略有區別:

  • 單引號

str='string test'

單引號''之間的字元原樣輸出,裡面的變數也會失效。其內部不能再有單引號,哪怕轉義符號都失效。

  • 雙引號
    1. your_name='your name'
    2. str="Hello ,world ,\"$your_name\"! \n"

雙引號裡面可以有變數,可以有轉義符號。

  • 字串拼接
    1. n1="abc"
    2. test="hello, "$n1" !"
    3. test1="hello, ${n1} !"
    4. echo $test $test1
  • 獲取字串長度

使用#標識變數長度

    1. str="abcdef"
    2.  
    3. #輸出字串長度
    4.  
    5. echo ${#str} 
  • 獲取子字串
    1. str="abcdef"
    2.  
    3. #下標從左至右,0開始,
    4.  
    5. echo ${str:1:4}
  • 查詢子字串

使用`符號

    1. str="hello world nihaome"
    2.  
    3. #查詢字元i或s的位置,反引號
    4.  
    5. echo `expr index "$str" is`

6、Shell陣列

bash僅支援一維陣列,可利用下標或表示式操作元素。

  • 定義陣列

shell中使用()表示陣列,元素用空格來分割。

    1. array=(1 2 3 4 5 6 7)
    2.  
    3. #或者
    4.  
    5. array=(
    6. a
    7. b
    8. c
    9. )
    10.  
    11. #也可以單獨定義,下標可以不連續,也無範圍限制。
    12.  
    13. array[0]=1
    14. array[1]=2
    15. array[3]=7
  • 讀取陣列
    1. variable=${array[index]}
    2.  
    3. # @符號代替index表示獲取所有元素
    4.  
    5. echo ${variable[@]}
  • 獲取陣列長度

類似字串的獲取

    1.  
    2. #獲取元素個數
    3.  
    4. length=${#array_name[@]}
    5.  
    6. #或者*萬用字元
    7.  
    8. length=${#array_name[*]}
    9.  
    10. #獲取陣列單個元素的長度
    11.  
    12. length_n=${#array_name[n]}

7、Shell註釋

使用#至於行首,表示該行註釋,shell無多行註釋,只能每行都#

  1. #-----------------------
  2. #我是個多行註釋
  3. #但是隻能這麼寫
  4. #-----------------------

要是多行程式碼需要註釋,可以將定義為函式,加{}包裹起來,該函式不被呼叫,則類似於註釋掉。

Shell傳遞引數

在執行shell指令碼時,可以向指令碼傳遞引數,指令碼內獲取引數的格式:$n,n代表數字編號,為指令碼內需要獲取的引數的編號。

1、例項

示例向指令碼傳遞三個引數,並輸出,$0為執行檔名:

  1. #!/bin/bash
  2. #傳參測試
  3.  
  4. echo "Shell 傳參測試";
  5. echo "file name: $0";
  6. echo "first variable: $1";
  7. echo "second variable: $2"
  8. echo "third variable: $3";

通過賦予許可權,或者指定執行,可實現輸出:

  1. $ chmod +x test.sh
  2. # $符號在次表示root使用者執行,下面是傳入1,2,3,三個數到指令碼
  3. $ ./test.sh 1 2 3 
  4.  
  5. #輸出結果:
  6. Shell 傳參測試
  7. file name: ./test.sh
  8. first variable: 1
  9. second variable 2
  10. third variable 3

另有幾個特殊字元處理引數:

引數處理

說明

$#

傳遞到指令碼的引數的個數

$*

以一個單字串顯示所有向指令碼傳遞的引數。

$$

指令碼執行的當前程序ID號

$!

後臺執行的最後一個程序的ID號

[email protected]

類似$*,使用時許加引號,並在引號中返回每個引數。

$-

顯示shell使用的當前選選項,類似set命令

$?

顯示最後命令的退出狀態。0 表示無錯誤。其他都是錯。

  1. #!/bin/sh
  2.  
  3. echo "Shell 傳遞引數例項!";
  4. echo "第一個引數為:$1";
  5.  
  6. echo "引數個數為:$#";
  7. echo "傳遞的引數作為一個字串顯示:$*";

執行效果:

  1. $ chmod +x test.sh
  2. $ ./test.sh 1 2 3
  3. Shell 傳遞引數例項!
  4. 第一個引數為:1
  5. 引數個數為:3
  6. 傳遞的引數作為一個字串顯示:1 2 3

$*[email protected]的異同:

  • 都是應用所有引數
  • 不同:只有在雙引號中體現。假設在指令碼執行時寫了三個引數 1、2、3,,則 ” * ” 等價於 “1 2 3”(傳遞了一個引數),而 “@” 等價於 “1” “2” “3”(傳遞了三個引數)。
    1.  
    2. #!/bin/bash
    3.  
    4.  
    5. echo "-- \$* demo ---"
    6. for i in "$*";do
    7. echo $i
    8. done
    9.  
    10. echo "-- \[email protected] demo ---"
    11. for i in "[email protected]"; do
    12. echo $i
    13. done

執行效果:

    1. $ chmod +x test.sh
    2. $ ./test.sh 1 2 3
    3. -- $* 演示 ---
    4. 1 2 3
    5. -- [email protected] 演示 ---
    6. 1
    7. 2
    8. 3

Shell陣列

Bash shell僅支援一維陣列,不限定大小,初始化時候不需要指定大小。下標0開始,()包裹,空格分割元素。

array=(a b c d)

  • 讀取陣列

格式${array[index]}

  1. #!/bin/bash
  2. my_array=(a b "c" d)
  3.  
  4. echo "first: ${my_array[0]}"
  5.  
  6. #然後執行檔案,獲得輸出結果
  7. #可用@或*來代替index獲取所有元素
  • 陣列長度

類似字串的長度獲取

${#array[index]}

Shell運算子

shell支援多種運算子:

  • 算數運算子
  • 關係運算符
  • 布林運算子
  • 字串運算子
  • 檔案測試運算子

原生Bash不支援簡單的數學運算,可以用awkexpr實現。

  1. #!/bin/sh
  2.  
  3. val=`expr 2 + 2`
  4. echo $val
  5.  
  6. #注意,expr用反引號,表示式和運算子之間必須有空格,2+2就不行。

1、算術運算子

若a = 10,b = 20

運算子

說明

舉例

+

加號

`expr $a + $b`,result = 30

-

減號

`expr $a - $b`,result = -10

*

乘號

`expr $a * $b`,result = 200

/

除號

`expr $b / $a`,result = 2

%

取餘

`expr $b % $a`,result=0

=

賦值

a=$b,將b的值賦給a

==

相等,比較數字,同則true。

[$a == $b]返回false

!=

不等,比較數字,不同的true。

[$a != $b]返回true。

  1. #!/bin/bash
  2. # author:菜鳥教程
  3. # url:www.runoob.com
  4.  
  5. a=10
  6. b=20
  7.  
  8. val=`expr $a + $b`
  9. echo "a + b : $val"
  10.  
  11. val=`expr $a - $b`
  12. echo "a - b : $val"
  13.  
  14. val=`expr $a \* $b`
  15. echo "a * b : $val"
  16.  
  17. val=`expr $b / $a`
  18. echo "b / a : $val"
  19.  
  20. val=`expr $b % $a`
  21. echo "b % a : $val"
  22.  
  23. if [ $a == $b ]
  24. then
  25.    echo "a 等於 b"
  26. fi
  27. if [ $a != $b ]
  28. then
  29.    echo "a 不等於 b"
  30. fi

執行結果:

  1. a + b : 30
  2. a - b : -10
  3. a * b : 200
  4. b / a : 2
  5. b % a : 0
  6. a 不等於 b
  •  

注意:條件表示式必須在[]之間,且必須有空格,如[$a==$b]是錯的!

*乘號需要在expr表示式內用\轉義

Mac電腦的shell的expr表示式:$((表示式))所以它的乘號*不用轉義

2、關係運算符

布林型別,關係運算符僅支援數字,除非字串的值也是數字。示例,若a = 10 ,b = 20:

運算子

說明

-eq

equal

-ne

not equal

-gt

great than

-lt

less than

-ge

great equal

-le

less equal

3、布林運算子

運算子

說明

!

運算,表示式為true,則返回false。

-o

運算,一個表示式為true,則返回true。

-a

運算,兩個都true,才返回true。

4、邏輯運算子

運算子

說明

&&

邏輯and

||

邏輯 or

5、字串運算子

運算子

說明

=

檢測兩字串是否相等

!=

檢測兩字串是否不等

-z

zero檢測字串長度是否為0,0則true

-n

not zero檢測字串長度是否非0。

str

檢測字串是否為空,不空則true。

6、檔案測試運算子

用於檢測類unix 檔案的各種屬性

操作符

說明

-b file

是否是塊裝置檔案,是則true

-c file

是否是字元裝置檔案,是則true

-d file

是否是目錄,是則true

-f file

是否是普通檔案(既非目錄,亦非裝置檔案),若是則true

-g file

是否設定了SGID位,是則true

-k file

是否設定粘著位,是則true

-p file

是否有名管道,是則true

-u file

是否設定SUID,是則true

-r file

是否可讀,是則true

-w file

是否可寫,是則true

-x file

是否可執行,是則true

-s file

是否為空或大小是否大於0,非空則true

-e file

是否存在,是則true

==注意shell指令碼的表示式都要在[]內哦==

Shell echo命令

類似於php的echo,shell的echo用於輸出字串,格式echo string

  • 顯示普通字串
  1. echo "Hello World"
  2. #可以不帶引號
  3. echo Hello World
  •  
  • 顯示轉義字元
    1. echo "\"It is a test\""
    2.  
    3. #輸出結果
    4.  
    5. "It is a test"
    •  
  • 顯示變數

read命令從標準輸入中讀取一行,並把輸入行的每個欄位指定給shell變數

    1.  
    2. #!/bin/sh
    3.  
    4. read name
    5. echo "$name It is a test"
    6.  
    7.  
    8. #執行效果:
    9.  
    10. [[email protected] ~]# sh test.sh
    11. OK                     #標準輸入
    12. OK It is a test        #輸出
    •  
  • 顯示換行
    1. echo -e "Ok ! \n" # -e 開啟轉義
    2. echo "It is a test"
    3.  
    4. #輸出結果:注意ok後面有換行
    5.  
    6. OK!
    7.  
    8. It it a tes
    •  
  • 顯示不換行
    1.  
    2. #!/bin/sh
    3.  
    4. echo -e "OK! \c" # -e 開啟轉義 \c 不換行
    5. echo "It is a test"
    6.  
    7. #結果:
    8.  
    9. OK! It is a test
    •  
  • 顯示結果定向至檔案

echo "It is a test" > test.txt

    • 1
  • 原樣輸出字元,不轉義不取變數,需要結合單引號
    1. echo '$name\"'
    2.  
    3. #輸出結果
    4.  
    5. $name\"
  • 顯示命令執行結果

==命令用`來包裹==

    1. echo `data`
    2.  
    3. #結果:
    4.  
    5. Thu Jul 24 10:08:46 CST 2014

Shell printf命令

類似C語言的printf()函式,shell使用printf會比echo更具有跨平臺移植性。可以類似C的printf()函式使用一些複雜的表示式,printf不支援自動換行,需要藉助\n

printf format-string [args...]

  • 1

示例,模擬shell輸出,

  1. $ echo "hello ,shell"
  2. hello ,shell
  3. $ printf "hello ,shell \n"
  4. hello ,shell
  5. $

指令碼化的printf命令使用:

  1. #!/bin/bash
  2. # author:菜鳥教程
  3. # url:www.runoob.com
  4.  
  5. printf "%-10s %-8s %-4s\n" 姓名 性別 體重kg  
  6. printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234 
  7. printf "%-10s %-8s %-4.2f\n" 楊過 男 48.6543 
  8. printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876 

執行指令碼,顯示結果:

  1. 姓名     性別   體重kg
  2. 郭靖     男      66.12
  3. 楊過     男      48.65
  4. 郭芙     女      47.99

%s,%c,%d,%f都是格式替換符,%-10s指一個寬度為10個字元(-表示左對齊,沒有則右對齊),任何字元都會被顯示在10個字元寬的字元內,如果不足則自動以空格填充,超過也會將內容全部顯示出來。

%-4.2f 指格式化為小數,其中.2指保留2位小數。

  1. #!/bin/bash
  2. # author:菜鳥教程
  3. # url:www.runoob.com
  4.  
  5. # format-string為雙引號
  6. printf "%d %s\n" 1 "abc"
  7.  
  8. # 單引號與雙引號效果一樣
  9. printf '%d %s\n' 1 "abc" 
  10.  
  11. # 沒有引號也可以輸出
  12. printf %s abcdef
  13.  
  14. # 格式只指定了一個引數,但多出的引數仍然會按照該格式輸出,format-string 被重用
  15. printf %s abc def
  16.  
  17. printf "%s\n" abc def
  18.  
  19. printf "%s %s %s\n" a b c d e f g h i j
  20.  
  21. # 如果沒有 arguments,那麼 %s 用NULL代替,%d 用 0 代替
  22. printf "%s and %d \n"
  • 2

Printf的轉移序列

序列

說明

\a

警告字元,通常為ASCII的BEL字元

\b

後退

\c

抑制不顯示輸出結果中任何姐wide換行字元(只在%b格式指示控制符下的引數字串中有效),而且任何留在引數裡的字元,任何接下來的採納書以及任何留在格式字串中的字元,都被忽略。

\f

換頁

\n

換行

\r

回車

\t

水平tab

\v

豎直tab

\\

轉義後輸出一個\符號

\d dd

表示1–3位的八進位制字元,僅在格式字串中有效。

\0 dd d

表示1–3位的八進位制字元

Shell text命令

shell中test命令用於測試條件是否成立,可進行數字、字元和檔案的條件測試

  1. #!/bin/bash
  2.  
  3. #用之前的各種運算子,測試test
  4. num1=100
  5. num2=200
  6. if test $[num1] -eq $[num2]
  7. then
  8.     echo 'true'
  9. else
  10.     echo 'false'
  11. fi

Shell 流程控制

區別於其他程式語言,shell的流程控制不可為空,如

  1. if(a>b){
  2.   System.out.println("ok");
  3. }else{
  4.   //此處不做任何事
  5. }
  •  

但是在shell中不能出現不做任何事的分支語句

1、if else

  • if語句格式
    1. if condition
    2. then
    3. command1
    4. command2
    5. ...
    6. fi # 是if的倒寫

每個句子可以用;分號結束,可以寫在一行好幾個語句。

  • if else
    1. if condition
    2. then
    3. command1
    4. command2
    5. ...
    6. else
    7. command
    8. fi
    •  
  • if else-if else
    1. if condition1
    2. then
    3. command1
    4. elif condition2 #類似python中,else if是寫作elif
    5. then
    6. command2
    7. else
    8. command
    9. fi
    • 9

2、for迴圈

shell的for迴圈格式:

  1. for var in item1 item2 ... itemN
  2. do
  3.     command1
  4.     command2
  5.     ...
  6.  
  7. done #for迴圈結束的標識
  8. #寫成一行
  9. for var in item1 item2 ... itemN;do command1; command2;...;done;
  • 9

3、while語句

格式:

  1. while condition
  2. do
  3.     command
  4. done
  5. #示例
  6.  
  7. #!/bin/sh
  8. int=1
  9. while(( $int<=5 ))
  10. do
  11.         echo $int
  12.         let "int++" # let是個關鍵命令
  13. done
  • 3

可以結合read命令接收輸入資訊

4、無限迴圈

  1. while :
  2. do
  3.     command
  4. done
  5.  
  6. #或者
  7. while true
  8. do
  9.     command
  10. done
  11.  
  12. #或者
  13. for (( ; ; ))
  •  

5、until迴圈

shell所有的until迴圈類似於一個特殊的for迴圈,知道滿足條件時候才停止。一般還是while

  1. until condition
  2. do
  3.     command
  4. done

條件可為任意測試條件,測試發生在迴圈末尾,因此迴圈至少執行一次—請注意這一點。

6、case

類似其他語言的switch…case語句

  1. case value in
  2. mode1)
  3.     command1
  4.     ...
  5.     ;; #case的結束標誌
  6. mode2)
  7.     command2
  8.     ...
  9.     ;;
  10. esac #case的反寫
  •  

value只會匹配一個case,或者不匹配,則mode可用*號通配

  1. echo '輸入 1 到 4 之間的數字:'
  2. echo '你輸入的數字為:'
  3. read aNum
  4. case $aNum in
  5.     1)  echo '你選擇了 1'
  6.     ;;
  7.     2)  echo '你選擇了 2'
  8.     ;;
  9.     3)  echo '你選擇了 3'
  10.     ;;
  11.     4)  echo '你選擇了 4'
  12.     ;;
  13.     *)  echo '你沒有輸入 1 到 4 之間的數字'
  14.     ;;
  15. esac
  •  

7、跳出迴圈

shell也使用breakcontinue來跳出迴圈。

  • break

跳出所有迴圈,終止後面的執行。

    1.  
    2. #!/bin/bash
    3.  
    4. while :
    5. do
    6.   echo -n "輸入 1 到 5 之間的數字:"
    7.   read aNum
    8.   case $aNum in
    9.       1|2|3|4|5) echo "你輸入的數字為 $aNum!"
    10.       ;;
    11.       *) echo "你輸入的數字不是 1 到 5 之間的! 遊戲結束"
    12.           break
    13.       ;;
    14.   esac
    15. done
  • continue

跳出本次迴圈,執行下一輪迴圈

    1.  
    2. #!/bin/bash
    3.  
    4. while :
    5. do
    6.   echo -n "輸入 1 到 5 之間的數字: "
    7.   read aNum
    8.   case $aNum in
    9.       1|2|3|4|5) echo "你輸入的數字為 $aNum!"
    10.       ;;
    11.       *) echo "你輸入的數字不是 1 到 5 之間的!"
    12.           continue
    13.           echo "遊戲結束"
    14.       ;;
    15.   esac
    16. done
    •  

8、esac

case語句區別於C語言,用esac作為結束標誌,);;標識每個case。

Shell函式

shell可以自定義函式,然後自己呼叫。函式格式:

  1. #function 關鍵字為可選項,引數也是可選
  2. [ function ] funname [()]
  3.  
  4. {
  5.  
  6.   action;
  7.  
  8.   [return int;]
  9.  
  10. }

說明:

  1. 可以帶function fun()定義,也可以fun()定義,不帶引數。
  2. 引數返回,可以顯示加: return 返回,若不加,則返回最後一條指令結果。
  1. #!/bin/bash
  2. # author:菜鳥教程
  3. # url:www.runoob.com
  4.  
  5. demoFun(){
  6.     echo "這是我的第一個 shell 函式!"
  7. }
  8. echo "-----函式開始執行-----"
  9. demoFun
  10. echo "-----函式執行完畢-----"
  • 0

含有返回值的函式:

  1. #!/bin/bash
  2. # author:菜鳥教程
  3. # url:www.runoob.com
  4.  
  5. funWithReturn(){
  6.     echo "這個函式會對輸入的兩個數字進行相加運算..."
  7.     echo "輸入第一個數字: "
  8.     read aNum
  9.     echo "輸入第二個數字: "
  10.     read anotherNum
  11.     echo "兩個數字分別為 $aNum 和