shell基本語法

lethe1203發表於2024-03-17

本節介紹一些常見的shell指令碼語法

一、常見運算子

數值運算子:

  • + :加法
  • - :減法
  • * :乘法
  • / :除法
  • % :取餘

字串運算子:

  • = :字串相等
  • != :字串不相等
  • -z :字串為空
  • -n :字串非空
  • str1 + str2 :拼接字串

數值比較運算子:

  • -eq:等於 (equal to)
  • -ne:不等於 (not equal to)
  • -lt:小於 (less than)
  • -le:小於等於 (less than or equal to)
  • -gt:大於 (greater than)
  • -ge:大於等於 (greater than or equal to)

二、迴圈語句

while迴圈

以下是 while 迴圈的基本語法:
while condition
do
    # 程式碼塊
done
其中,condition 是一個需要評估的條件表示式,可以是關係表示式、邏輯表示式或函式返回值等。只有當 condition 為真時,迴圈中的程式碼塊才會被執行。程式碼塊由 dodone 來標記。
下面是一個簡單的示例,演示了 while 迴圈的用法:
count=0
while [ $count -lt 5 ]
do
    echo "Count: $count"
    count=$((count+1))  # 自增 count 變數
done
以上程式碼會輸出從 0 到 4 的計數值。while 迴圈首先檢查條件 $count -lt 5 是否為真,如果為真,則會執行迴圈中的程式碼塊。在每次迭代時,會輸出當前的計數值並將 count 變數自增。當 count 達到 5 時,條件為假,迴圈結束。

for迴圈

以下是 for 迴圈的基本語法:
for variable in list
do
    # 程式碼塊
done
其中,variable 是一個用於儲存當前迭代元素的變數名,list 是需要迭代的元素列表或範圍。
list 可以是用空格分隔的多個值,也可以是利用萬用字元來匹配多個檔名。另外,還可以使用 {start..end} 表示式來生成一個範圍內的數字序列。
下面為兩個簡單示例:
for num in {1..5}
do
    echo "Number: $num"
done
以上程式碼會迭代從 1 到 5 的數字序列,並輸出每個數字。 需要注意的是,在 for 迴圈中,變數的賦值使用的是in關鍵字,而不是等號(=)。 for 迴圈還支援其他控制語句,例如 break 和 continue,用於提前終止迴圈或跳過當前迭代
#/bin/bash.sh

for times in $(seq 1 10)
do
        echo "$times"
done
表示輸出1-10

三、判斷語句

if語句

if 結構用於基於給定條件進行條件判斷,並根據判斷結果來決定執行哪個程式碼塊。它可以包含多個條件分支,每個分支由 ifthenelif(可選)和 else(可選)組成。
# 單分支語句 ---比較大小
        if (條件表示式);then
                語句1
        fi

# 雙分支if 語句
        if (表示式)
                語句1
        else
                語句2
        fi

# 多支條件語句 
        if (表示式)
                語句1
        elif
                語句2
        elif
                語句2
        fi  
下面為一簡單舉例:
score=85

if [ $score -ge 90 ]; then
    echo "優秀"
elif [ $score -ge 80 ]; then
    echo "良好"
else
    echo "及格"
fi
以上程式碼根據變數 score 的值進行條件判斷,並輸出相應的成績等級。

case語句

case 結構用於基於不同模式匹配執行對應的程式碼塊。它類似於多個 if-else 分支判斷,但更適用於比較複雜的模式匹配需求。
以下是 case 結構的基本語法:
case expression in
    pattern1)
        # 程式碼塊1
        ;;
    pattern2)
        # 程式碼塊2
        ;;
    pattern3)
        # 程式碼塊3
        ;;
    *)
        # 預設程式碼塊
        ;;
esac
其中,expression 是要進行匹配的表示式,pattern1pattern2pattern3 是不同的模式,* 是預設模式。
例如:
fruit="apple"

case $fruit in
    "apple")
        echo "這是一個蘋果"
        ;;
    "orange" | "lemon")
        echo "這是一個橘子或檸檬"
        ;;
    *)
        echo "未知水果"
        ;;
esac
以上程式碼根據變數 fruit 的值進行模式匹配,並輸出相應的提示資訊。
注意,在 case 結構中,每個模式末尾需要使用雙分號 ;; 表示結束當前分支的程式碼塊。

四、常見命令

let命令

let 是一種用於執行算術運算的內建命令。它可以用於執行基本的數值計算,並將結果賦給變數
以下是一些示例說明 let 命令的使用:
let a=5+3  # 將 5 + 3 的結果賦給變數 a
echo $a   # 輸出結果為 8

let "b = 2 * (10 - 4)"  # 將 2 * (10 - 4) 的結果賦給變數 b
echo $b   # 輸出結果為 12

c=7
let c++    # 對變數 c 進行自增操作,等價於 c=c+1
echo $c   # 輸出結果為 8

let "d = (5 > 3) && (2 < 4)"  # 執行邏輯運算,並將結果賦給變數 d
echo $d   # 輸出結果為 1(真)
需要注意的是,let 命令執行的是整數運算,如果涉及到浮點數運算,let 命令會進行截斷取整。

[[ ]]、[]

單括號 [ ]: 單括號 [ ] 是最基本的條件測試結構,在早期版本的 Bash 中被廣泛使用。它可以用於測試多種條件,包括字串比較、數值比較和檔案屬性等。
使用單括號時,通常需要在變數周圍新增引號,以避免一些特殊字元的問題。並且,需要注意使用不同的比較符號(例如 =!=-eq)來進行條件判斷。
例如:
shellCopy Code
if [ "$var" = "abc" -a "$num" -gt 10 ]; then
    echo "條件滿足"
else
    echo "條件不滿足"
fi
雙括號 [[ ]]: 雙括號 [[ ]] 是 Bash shell 的擴充套件條件測試結構,提供了更多的功能和便利性。它支援字串模式匹配、正規表示式匹配、邏輯運算子的巢狀等。
與單括號不同,雙括號內的變數可以不使用引號進行包裹,這意味著在條件測試中可以直接使用變數而不必擔心特殊字元的影響。
例如:
shellCopy Code
if [[ $var == "abc" && $num -gt 10 ]]; then
    echo "條件滿足"
else
    echo "條件不滿足"
fi
總結一下,單括號 [ ] 是最基本的條件測試結構,適用於基本的條件判斷;而雙括號 [[ ]] 是擴充套件的條件測試結構,提供了更多的功能和便利性,可以進行更靈活的條件判斷。在使用時,建議優先使用雙括號 [[ ]],除非必須與其他 shell 相容或需要特定的行為時,才使用單括號 [ ]

()、(())

()() 是用於建立子shell(subshell)的一種方式,在子shell 中執行相關的命令。子shell 是一個獨立的程序,具有自己的環境變數和變數作用域。
使用 () 可以將一組命令括在括號內,並作為一個整體進行處理。這樣可以在子shell 中執行這組命令,並在子shell 完成後返回到原來的shell 中。
例如:
shellCopy Code
#!/bin/bash

count=0
(
    count=$((count+1))
    echo "This is in the subshell. Count: $count"
)
echo "Back to the main shell. Count: $count"
以上程式碼建立了一個子shell,在子shell 中對 count 進行自增操作並輸出結果。然後,回到主shell 輸出原始的 count 值。
(())(()) 是用於執行算術運算和邏輯運算的結構,在其中可以使用變數和運算子進行數值計算和邏輯判斷。
(()) 結構會對其中的表示式進行求值,並返回計算結果。它支援基本的算術運算子、邏輯運算子和位運算子。
例如:
a=5
b=3
result=$((a + b))
echo "The result is: $result"
以上程式碼使用 (()) 結構進行算術運算,計算變數 ab 的和,並將結果賦給 result 變數。然後輸出計算結果。
需要注意的是,在 (()) 結構中不需要使用美元符號 $ 來引用變數,直接使用變數名即可。
綜上所述,() 是用於建立子shell,可以在其中執行一組命令;(()) 是用於執行算術運算和邏輯運算的結構,用於進行數值計算和邏輯判斷。

read -p

read -p 是一個用於讀取使用者輸入的命令。-p 引數用於在讀取輸入之前顯示提示資訊。
示例:
#!/bin/bash
read -p "請輸入您的名字: " name
echo "您好,$name!"
上述示例中,使用 read -p 提示使用者輸入名字,並將使用者輸入的值儲存在 name 變數中。然後透過 echo 命令輸出歡迎訊息,包含使用者輸入的名字。
執行指令碼時,使用者將看到一個提示,等待輸入名字。使用者輸入名字後,指令碼將繼續執行並輸出歡迎訊息。

-d

-d 是用作條件測試命令 [ ]test 的選項之一,用於檢查給定路徑是否為一個存在的目錄
以下是一個示例,展示瞭如何使用 -d 來檢查目錄是否存在:
path="/data/rivers"

if [ -d "$path" ]; then
    echo "目錄存在"
else
    echo "目錄不存在"
fi
在上述示例中,如果 /data/rivers 目錄存在,則輸出 "目錄存在";否則輸出 "目錄不存在"。
需要注意的是,在條件測試中,path 需要使用引號引起來,以避免路徑中存在空格等特殊字元時出現問題。

-a

在條件測試中,使用 -a 可以將多個條件連線起來,並在所有條件都為真時返回真值。-a 實際上是邏輯 AND 運算子的一種替代方式。
但需要注意的是,使用 -a 存在一些問題和不推薦的情況。根據 POSIX 標準,應使用雙中括號 [[ ]] 來進行條件測試,且不使用 -a 選項。另外,還可以使用雙和號 && 來代替 -a,更加簡潔和易讀。因此,建議優先使用 [[ ]]&& 來執行邏輯 AND 操作,而非使用 -a
以下是一個示例,展示了 -a 的用法,說明了如何在條件測試中使用 -a 執行邏輯 AND 操作:
if [ "$var1" -gt 10 -a "$var2" == "abc" ]; then
    echo "條件滿足"
else
    echo "條件不滿足"
fi
在上述示例中,如果變數 var1 大於 10 並且變數 var2 的值等於 "abc",則條件被認為是真,輸出 "條件滿足"。否則輸出 "條件不滿足"。

%F %T

通常用於格式化日期和時間的字串輸出。
  • %F 是用於格式化日期的佔位符,它代表完整的日期,包括年份、月份和日期,使用格式為 YYYY-MM-DD
  • %T 是用於格式化時間的佔位符,它代表完整的時間,包括小時、分鐘和秒鐘,使用 24 小時制,格式為 HH:MM:SS
這些佔位符通常用於命令如 date 等,用於獲取當前日期和時間,並進行格式化輸出。
以下是一個示例,演示瞭如何使用 %F%T 進行日期和時間的格式化輸出:
current_date=$(date +'%F')
current_time=$(date +'%T')

echo "Today's date is: $current_date"
echo "Current time is: $current_time"
以上程式碼會獲取當前的日期和時間,並將其格式化為 %F%T 所示的格式進行輸出。

set -x

set -x 是一個用於開啟除錯模式的選項。當執行這個命令後,Shell 會將指令碼的每一行命令都顯示出來,並在命令執行之前先輸出該行命令。
以下是一個示例,展示瞭如何使用 set -x 開啟除錯模式:
#!/bin/bash

set -x

# 以下是指令碼的主要邏輯
echo "開始執行指令碼"
for i in {1..5}; do
    echo "Loop $i"
done
echo "指令碼執行完畢"

set +x

# 除錯模式已關閉,以下的命令不會顯示
echo "除錯模式已關閉"
在上述示例中,set -x 命令在指令碼的開頭設定了除錯模式。當指令碼執行時,每個命令都會被顯示出來,以及其執行結果。set +x 命令用於關閉除錯模式,在該命令之後的命令將不再顯示。
透過開啟除錯模式,可以更直觀地看到指令碼執行過程中每一行命令的執行情況,幫助進行除錯或排錯。

$1 $2 ...

$1$2 是命令列引數的佔位符,用於引用在指令碼執行時傳遞給它的引數。
  • $1 代表第一個命令列引數。
  • $2 代表第二個命令列引數。
在Shell指令碼中,當你執行指令碼並傳遞引數時,可以透過這些變數來引用和訪問這些引數。
以下是一個示例,演示瞭如何在Shell指令碼中使用 $1$2
#!/bin/bash

echo "第一個引數: $1"
echo "第二個引數: $2"
假設指令碼名為 script.sh,你可以透過以下方式執行指令碼並傳遞兩個引數:
./script.sh value1 value2
指令碼會分別輸出傳遞的兩個引數的值。在此示例中,$1 的值將是 "value1",$2 的值將是 "value2"。