Shell 腳本編程


Shell 腳本編程

同傳統的編程語言一樣,shell 提供了很多特性,這些特性可以使你的 shell 腳本編程更為有用。

創建 Shell 腳本

一個 shell 腳本通常包含如下部分:首行+注釋+內容

  • 首行

第一行內容在腳本的首行左側,表示腳本將要調用的shell解釋器,內容如下:

#!/bin/bash

#!符號能夠被內核識別成是一個腳本的開始,這一行必須位於腳本的首行,/bin/bash 是 bash 程序的絕對路徑,在這里表示后續的內容將通過 bash 程序解釋執行。

  • 注釋

注釋符號 # 放在需注釋內容的前面,如下:

#! /bin/bash
# my first shell script(注釋)
  • 內容

可執行內容和 shell 結構

#! /bin/bash
echo "hello,world"

Shell 腳本的權限

一般情況下,默認創建的腳本是沒有執行權限的

# ll | grep bash
-rw-r--r--. 1 root root      56 11月  1 07:19 bash.sh

沒有權限不能執行,需要賦予可執行權限

# chmod +x bash.sh
# ll | grep bash
-rwxr-xr-x. 1 root root      56 11月  1 07:19 bash.sh

Shell 腳本的三種執行方式

  • 1、輸入腳本的絕對路徑或相對路徑

    注:相對路徑不能省略 ./

  • 2、bash (或 sh) + 腳本

    注:當腳本沒有 x 權限時,root 和文件所有者通過該方式可以正常執行

    注:創建 bash 新環境並執行腳本,執行完釋放 bash 環境

  • **3、在腳本的路徑前再加 ". " 或 source **

    注:第一種和第二種會創建一個 bash 環境,不同 bash 中的變量無法共享;但是第三種方式是在同一個 bash 里面執行的

Shell 變量

  • 變量:是 shell 傳遞數據的一種方式,用來代表每個取值的符號名;當 shell 腳本需要保存一些信息時,如一個文件名或是一個數字,就把它存放在一個變量中

  • 變量設置規則:

    1. 變量名稱可以由字母,數字和下划線組成,但是不能以數字開頭,環境變量名建議大寫,便於區分

    2. 在 bash 中,變量的默認類型都是字符串型,如果要進行數值運算,則必須指定變量類型為數值型。

    3. 變量用等號連接值,等號左右兩側不能有空格

  1. 變量的值如果有空格,需要使用單引號或者雙引號包括。

變量分類

Linux Shell 的變量分為用戶自定義變量、環境變量、位置參數變量和預定義變量

# set # 可以查看系統中存在的所有變量
  • 系統變量:保存和系統操作環境相關的數據,如 $HOME、$PWD、$SHELL、$USER 等

  • 位置參數變量:主要用來向腳本中傳遞參數或數據,變量名不能自定義,變量作用固定

  • 預定義變量:是 Bash 中已經定義好的變量,變量名不能自定義,變量作用也是固定的

用戶自定義變量

用戶自定義的變量由字母或下划線開頭,由字母,數字或下划線序列組成,並且大小寫字母意義不同,變量名長度沒有限制。

  • 設置變量

    習慣上用大寫字母來命名變量,變量名以字母表示的字符開頭,不能用數字。

    # name=zs
    
  • 變量調用

    在使用變量時,要在變量名前加上前綴 “$”
    使用 echo 命令查看變量值。

# echo $name
  • 變量賦值
    1. 定義變量時賦值:變量=值
# STR="hello world"
# A=9

​ 2. 將一個命令的執行結果賦給變量

# A=`ls -la`  # 反引號,運行里面的命令,並把結果返回給變量A
# A=$(ls -la) # 等價於反引號
# echo $A
# aa=$((4+5))

​ 3. 將一個變量賦給另一個變量

 # A=$STR
  • 變量疊加
# aa=123
# cc="$aa"456  # 使用雙引號
# cc=${aa}456  # 使用{}
# cc='$aa'456  # 無法疊加變量

單引號和雙引號的區別:

  • 雙引號:雙引號里的變量名會替換為變量值

  • 單引號:會將所有特殊字符脫意,里面的內容會原樣全部輸出

# NUM=10   
# SUM="$NUM hehe"  
# echo $SUM   
10 hehe
# SUM='$NUM hehe'  
# echo $SUM   
$NUM hehe
  • 列出所有的變量

    # set 
    
  • 刪除變量

    # aa=22
    # echo $aa
    # unset aa
    # set
    # echo $aa
    
    # readonly bb=2 # 聲明靜態的變量不能unset
    # unset bb
    -bash: unset: bb: cannot unset: readonly variable
    

作用域:用戶自定義的變量,作用域為當前的 shell 環境。

環境變量

用戶自定義變量只在當前的 shell 中生效,而環境變量會在當前 shell 和其所有子 shell 中生效。如果把環境變量寫入相應的配置文件,那么這個環境變量就會在所有的 shell 中生效。

export 變量名=變量值 # 申明環境變量

作用域:當前 shell 以及所有的子 shell

位置參數變量

變量 描述
$n n為數字,$0代表命令本身,$1-$9代表第一到第9個參數, 十以上的參數需要用大括號包含,如${10}。
$* 代表命令行中所有的參數,把所有的參數看成一個整體。以"$1 $2 … $n"的形式輸出所有參數
$@ 代表命令行中的所有參數,把每個參數區分對待。以"$1" "$2" … "$n" 的形式輸出所有參數
$# 代表命令行中所有參數的個數。添加到shell的參數個數
  • shift 指令

    參數左移,每執行一次,參數序列順次左移一個位置,$# 的值減1,用於分別處理每個參數,移出去的參數不再可用

    $ 和 $@ 的區別*

    $* 和 $@ 都表示傳遞給函數或腳本的所有參數

    • 不被雙引號" "包含時,都以"$1" "$2" … "$n" 的形式輸出所有參數
    • 被雙引號" "包含時
      • "$*" 會將所有的參數作為一個整體,以"$1 $2 … $n"的形式輸出所有參數
      • "$@" 會將各個參數分開,以"$1" "$2" … "$n" 的形式輸出所有參數

預定義變量

變量 描述
$? 執行上一個命令的返回值 執行成功,返回0,執行失敗,返回非0(具體數字由命令決定)
$$ 當前進程的進程號(PID),即當前腳本執行時生成的進程號
$! 后台運行的最后一個進程的進程號(PID),最近一個被放入后台執行的進程 &(后台運行)

read 命令

read [選項] 值

read -p(提示語句) -n(字符個數) -t(等待時間,單位為秒) –s(隱藏輸入)

運算符

// 無法正確運算(變量默認是字符串類型)
# num1=11
# num2=22
# sum=$num1+$num2 
# echo $sum

格式 : expr m + n 或 $((m+n))

expr 命令:對整數型變量進行算術運算

# expr 3 + 5  // expr 運算符間要有空格
# expr 3 – 5
# echo `expr 10 / 3`
# expr 3 \* 10   // \ 是轉義符

計算(2 +3 )× 4 的值

# S=`expr 2 + 3`
# expr $S \* 4

# expr `expr 2 + 3` \* 4
# echo $(((2 + 3) * 4)) //推薦使用

$() 、${} 與 $(()) 的區別

  • $( ):用途和反引號``一樣,用來表示優先執行的命令(與反引號可讀性更高)

    # echo $(ls -l)
    
  • ${ } :獲取變量值 (與$相比變量更容易識別)

    # echo ${PATH}
    
  • $((運算內容)) :適用於數值運算(比expr更簡潔)

    # echo $((3+1*4))
    

條件測試

內置 test 命令

test 命令可用於測試表達式,支持測試的范圍包括:字符串比較,算術比較,文件存在性、屬性、類型等判斷。例如,判斷文件是否為空、文件是否存在、是否是目錄、變量是否大於5、字符串是否等於"longshuai"、字符串是否為空等等。在shell 中,幾乎所有的判斷都使用 test 命令實現。

內置 test 命令常用操作符號有兩種格式:

  • test expression
  • [ expression ] # expression表達式首尾都必須要有空格(推薦使用)

表達式的結果為真,則 test 的返回值為 0,否則為非 0

當表達式的結果為真時,則變量$?的值就為 0,否則為非 0

字符串測試:

  • test str1 == str2 或 [ str1 == str2 ] #測試字符串是否相等 =
  • test str1 != str2 或 [ str1 != str2 ] #測試字符串是否不相等
  • test str1 或 [ str1 ] #測試字符串是否不為空,(不為空:true,為空:false)
  • test -n str1 或 [ -n str1 ] #測試字符串是否不為空
  • test -z str1 或 [ -z str1 ] #測試字符串是否為空

注意:程序世界中一般都用1表示true,0表示false。但0表示失敗的話,沒有具體詳細的失敗含義,比如失敗原因可能是輸入參數不合法,可能是數據不存在等等,使用0來涵蓋這些所有的異常原因不利於問題排查。

因此在 Bash 中,用 0 表示 true,非0 表示 false。我們可以使用1-255中的任何一個數字來表示某個具體的錯誤,1是一個普遍的錯誤,126意味着一個文件不能被執行,127意味着’找不到命令’等。

; 命令連接符號,可以連接多個命令一起執行

  • && 邏輯與條件滿足,才執行后面的語句
# [ "hello" == "hello" ] && echo yes
  • || 邏輯或,條件不滿足,才執行后面的語句
[ "hello" == "world" ] && echo yes || echo no

整數測試:

符號 運算符
-eq ==
-ge >=
-gt >
-le <=
-lt <
-ne !=
  • test int1 -eq int2 或 [ int1 -eq int2 ] # 測試整數是否相等 equals
  • test int1 -ge int2 或 [ int1-ge int2 ] # 測試int1是否>=int2
  • test int1 -gt int2 或 [ int1 -gt int2 ] # 測試int1是否>int2
  • test int1 -le int2 或 [ int1 -le int2 ] # 測試int1是否<=int2
  • test int1 -lt int2 或[ int1 -lt int2 ] # 測試int1是否<int2
  • test int1 -ne int2 或 [ int1 -ne int2 ] # 測試整數是否不相等
# test 100 –ge 100;echo $?
# [ 100 -ge 100 ];echo $?

文件測試:

  • test -d file 或 [ -d file ] # 指定文件是否目錄
  • test –e file 或 [ -e file ] # 文件是否存在 exists
  • test -f file 或 [ -f file ] # 指定文件是否常規文件
  • test –L file [ -L file ] # 文件存在並且是一個符號鏈接
  • test -r file [ -r file ] # 指定文件是否可讀
  • test -w file [ -w file ] # 指定文件是否可寫
  • test -x file [ -x file ] # 指定文件是否可執行
# test -d install.log  #是否為目錄
# test –r install.log  #文件是否可讀
# test –f xx.log ; echo $? #是否是常規文件
# [ -L service.soft ] && echo “is a link” #文件存在並且是一個符號鏈接
# test -L /bin/sh ;echo $? #文件存在並且是一個符號鏈接
# [ -f /root ] && echo “yes” || echo “no” #是否是常規文件

多重條件測試:

  • 條件1 –a 條件2 (邏輯與:兩個都成立,則為真)
  • 條件1 –o 條件2 (邏輯或 :只要有一個為真,則為真)
  • !條件 (邏輯非:取反)

注意與 && 和 || 的區別,不要混淆在一起

 num=100
 [ $num -gt 50 -a $num -gt 100 ];echo $?
 [ $num -gt 50 -o $num -gt 10 ];echo $?

流程控制語句

if/else命令

1, 單分支if條件語句

if [ 條件判斷式 ]
  then
    代碼塊
fi

或者

if [ 條件判斷式 ] ; then 
  代碼塊
fi
#!/bin/sh
if [ $USER == "root" ];then
  echo "super man"
fi

單分支條件語句注意事項:

  • if 語句使用 fi 結尾,和一般語言使用大括號結尾不同

  • [ 條件判斷式 ] 就是使用 test 命令判斷,所以中括號和條件判斷式之間必須有空格

2,多分支if條件語句

if [ 條件判斷式1 ]
  then
   當條件判斷式1成立時,執行程序1
elif  [ 條件判斷式2 ] 
  then    
  當條件判斷式2成立時,執行程序2
...省略更多條件
else
  當所有條件都不成立時,最后執行此程序
fi

case 命令

case 命令是一個多分支的 if/else命令,case 變量的值用來匹配 value1,value2,value3 等等。匹配到后則執行跟在后面的命令直到遇到雙分號為止(;😉,case 命令以 esac 作為終止符。

for 循環

for 循環命令用來在一個列表條目中執行有限次數的命令。比如,你可能會在一個姓名列表或文件列表中循環執行同個命令。

  • for 命令后緊跟一個自定義變量、一個關鍵字 in 和一個字符串列表(可以是變量)
  • 第一次執行 for 循環時,字符串列表中的第一個字符串會賦值給自定義變量,然后執行循環命令,直到遇到done語句;
  • 第二次執行 for 循環時,會右推字符串列表中的第二個字符串給自定義變量,依次類推,直到字符串列表遍歷完。

for 語法格式

  • 第一種:
#!/bin/bash
for i in 1 2 3 
do
 echo $i
done
  • 第二種:
for ((i = 0; i <= 5; i++))
do
 echo "welcome $i times"
done

while 循環

while 命令根據緊跟其后的表達式來判斷是否執行 while 循環,當 表達式執行后的返回值為0時,則執行 while 循環語句塊,直到遇到 done 語句,然后再返回到 while 命令,判斷表達式的返回值,當得打返回值為非0時,則終止 while 循環。

while 語法格式

  • 第一種(循環條件)
while expression
do
	代碼
done
  • 第二種(死循環)
while :
do
	代碼
done

自定義函數

函數代表着一個或一組命令的集合,表示一個功能模塊,常用於模塊化編程。

以下是關於函數的一些重要說明:

  • 在 shell 中,函數必須先定義再調用

  • 使用 return value 來獲取函數的返回值

  • 函數在當前 shell 中執行,可以使用腳本中的變量

函數定義格式

function 函數名()
{
	命令1….
	命令2….
	return 返回值變量
}

注意:

  • 如果函數名后沒有(),在函數名和 { 之間,必須要有空格以示區分

  • 函數返回值,只能通過$? 系統變量獲得,可以顯示加:return 返回值,如果不加將以最后一條命令運行結果,作為返回值

腳本調試

  • sh -x script:這將執行該腳本並顯示所有變量的值。
  • set -x :在shell腳本里添加,對部分腳本調試
  • sh -n script:不執行腳本只是檢查語法的模式,將返回所有語法錯誤。
  • sh –v script:執行並顯示腳本內容


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM