SHELL 語法以及範例

2021-04-19 03:00:19

語言簡介

Bash,Unix shell的一種,在1987年由布萊恩·福克斯為了GNU計劃而編寫。
1989年釋出第一個正式版本,原先是計劃用在GNU作業系統上,但能執行於大多數類Unix系統的作業系統之上,包括Linux與Mac OS X v10.4起至macOS Mojave都將它作為預設shell,
而自macOS Catalina,預設Shell以zsh取代。
-- 來自於維基百科

語法與特性

bash的命令語法是Bourne shell命令語法的超集。
數量龐大的Bourne shell指令碼大多不經修改即可以在bash中執行,只有那些參照了Bourne特殊變數或使用了Bourne的內建命令的指令碼才需要修改。
bash的命令語法很多來自Korn shell(ksh)和C shell(csh),例如命令列編輯,命令歷史,目錄棧,$RANDOM和$PPID變數,以及POSIX的命令置換語法:$(...)。
作為一個互動式的shell,按下TAB鍵即可自動補全已部分輸入的程式名,檔名,變數名等等。

使用'function'關鍵字時,Bash的函數宣告與Bourne/Korn/POSIX指令碼不相容(Korn shell 有同樣的問題)。
不過Bash也接受Bourne/Korn/POSIX的函數宣告語法。
因為許多不同,Bash指令碼很少能在Bourne或Korn直譯器中執行,除非編寫指令碼時刻意保持相容性。
然而,隨著Linux的普及,這種方式正變得越來越少。不過在POSIX模式下,Bash更加符合POSIX。

語法

變數定義

name="foo"

注意,變數名和等號之間不能有空格,這可能和你熟悉的所有程式語言都不一樣。
同時,變數名的命名須遵循如下規則:

  • 命名只能使用英文字母,數位和下劃線,首個字元不能以數位開頭。
  • 中間不能有空格,可以使用下劃線(\_)。
  • 不能使用標點符號。
  • 不能使用bash裡的關鍵字(可用help命令檢視保留關鍵字)。

使用變數

使用只需要加上美元符號 $ 即可

列印: echo $name
列印結果: foo

如果不加美元符號, 則就是一個字串:

列印: echo name
列印結果: name

當然變數的兩邊也可以加上花括號:

name="foo"

echo "I am good at ${name} Script"
echo "I am good at $name Script"

// 這兩句是等價的 花括號的優勢在於空格

定義唯讀變數

url="mo.fish"
readonly url

url="jandan.net"

再次賦值時,即會報錯: index.sh: line 14: url: readonly variable

刪除變數

name="foo"
url="mo.fish"

unset url
unset name

注意: 唯讀變數是無法刪除的, 報錯: index.sh: line 14: unset: url: cannot unset: readonly variable

普通變數被刪除後,列印結果為空

關於字串

在 shell 中 儘量使用雙引號
因為單引號中,變數是無效的, 這是很重要的一點

字串拼接

通過空格即可拼接:

name="foo"
url="mo.fish"

echo $name $url

字串長度

加上 # 即可

name="foo"
echo ${#name}

字串擷取

使用冒號:

url="mo.fish"

echo ${url:1:3}
// 列印: o.f
// 從 0 開始  第一位至第三位

陣列

陣列定義

用括號來表示陣列,陣列元素用"空格"符號分割開。

arr=($name $url)
echo ${arr[1]}

// echo ${arr} 等於 echo ${arr[0]}「

列印所有陣列

這一點是比較特殊的

arr=($name $url)
echo ${arr[@]}

獲取陣列長度

和字串類似:

length=${#arr[@]}
echo $length

流程控制

if else

if 和 其他語言有些不太相同:

if [ $name=="foo" ]
then
  echo "name 是 foo"
fi
// fi 表示結束  因為不像其他語言 沒有 {}

而 else 和 if else 的話 這樣寫:

if [ $name != "foo" ]
then
  echo "name 是 foo"
else
  echo "不符合"
fi
if [ $name == "bar" ] ;then
  echo "name 是 bar"
elif [ $name == "foo" ]; then
  echo "name 是 foo"
else
  echo "不符合"
fi

這種使用 ; then 的寫法 可能更加符合我們的直覺

for

for loop in 1 2 3 4 5
do
    echo "The value is: $loop"
done

while

int=1
while(( $int<=5 ))
do
    echo $int
    let "int++"
done

for 和 while 都只用一個簡單例子

函數

定義

GrewerFn(){
    echo "這是我的第一個 shell 函數!"
}

執行

執行是一個簡單的操作:

GrewerFn(){
    echo "這是我的第一個 shell 函數!"
}

GrewerFn

只需寫上函數名稱 即可呼叫

引數

GrewerFn(){
    echo "第一個引數為 $1 !"
    echo "第二個引數為 $2 !"
    echo "列印所有引數 $@ !"
}

GrewerFn 1 "qwer" "zxc"

通過這樣的方法能夠傳遞引數

而裡面 $1, $2 這樣的引數處理可以引數下面的表格:

引數處理說明
$#傳遞到指令碼或函數的引數個數
$*以一個單字串顯示所有向指令碼傳遞的引數
$$指令碼執行的當前程序ID號
$!後臺執行的最後一個程序的ID號
$@與$*相同,但是使用時加引號,並在引號中返回每個引數。
$-顯示Shell使用的當前選項,與set命令功能相同。
$?顯示最後命令的退出狀態。0表示沒有錯誤,其他任何值表明有錯誤。

互動

獲取使用者輸入

read

使用的方法很簡單:

read yourName
echo "you name is $yourName"

後面還能加引數, 如
-p 引數,允許在 read 命令列中直接指定一個提示。

    read -p "輸入網站名:" website
    echo "你輸入的網站名是 $website"

限定字元:

read -n1 -p "Do you want to continue [Y/N]?" answer
case $answer in
Y | y)
      echo "fine ,continue";;
N | n)
      echo "ok,good bye";;
*)
     echo "error choice";;
esac
select
PS3='Please enter your choice: '
options=("Option 1" "Option 2" "Option 3" "Quit")
select opt in "${options[@]}"
do
    case $opt in
        "Option 1")
            echo "you chose choice 1"
            ;;
        "Option 2")
            echo "you chose choice 2"
            ;;
        "Option 3")
            echo "you chose choice $REPLY which is $opt"
            ;;
        "Quit")
            break
            ;;
        *) echo "invalid option $REPLY";;
    esac
done

小補充

PS1——預設提示符
PS2——再談提示符
PS3——Shell指令碼中使用select時的提示符
PS4——PS4-「set -x"用來修改跟蹤輸出的字首

具體參考: https://os.51cto.com/art/2012...

其他

還有一個比較熱門的 expect ,這裡就不多說了, 需要下載, 有些嵌入式環境不支援

常用場景

  • Linux 上的自動指令碼: 如使用 crontab 執行定時任務, 讀取修改檔案, 我之前的一篇文章也使用到了他:https://segmentfault.com/a/11...
  • 登入指令碼等等, 可以省略很多麻煩的過程

    當然相較於其他語言, 都是可以這樣做, shell 的優勢就在於原生支援
    
  • 初始化環境, 使用指令碼一鍵初始化整個 linux 環境, 如果接觸過 cli 的話應該知道他的作用

結語

shell 作為 linux 官方的語言, 他附帶了很多功能, 給我們提供了很多便利
在沒有環境的時候, 也可以直接執行, 學會此語言, 可以幫助你在伺服器領域大展拳腳

以上部分例子來源於 https://www.runoob.com/linux/...