Linux Shell 腳本編程以前一直沒有系統的去學習,在寫 Shell 腳本的時候總須要現查各類語法。本文章以編程語言的維度去系統的學習 Shell 腳本編程。html
Linux Shell 是與 Linux 系統交互的一個應用程序,咱們經過這個程序能夠操做 Linux 系統的內核服務。linux
執行 $cat /etc/shells
, 能夠看到系統中如今可用的 Shell 解釋器git
# List of acceptable shells for chpass(1). # Ftpd will not allow users to connect who are not using # one of these shells. /bin/bash /bin/csh /bin/ksh /bin/sh /bin/tcsh /bin/zsh /usr/local/bin/zsh
現代的 Linux 系統中 /bin/sh
已經被 /bin/bash
, 做爲 Linux 默認的 Shell.github
輸入 $echo $SHELL
能夠看到當前系統的 Shell.正則表達式
Shell 腳本 (Shell Script), 是爲 Shell 編寫的一個腳本程序。咱們說的 Shell 一般指的是 Shell 腳本。shell
Shell 腳本屬於弱類型的腳本語言,在使用的時候不須要提早定義變量類型。express
可能的坑:編程
- 賦值變量不能有美圓符號 (
$
)- 賦值語句等號 (
=
) 左右都不能有空格
#!/bin/bash # 直接賦值 name="cizel" # 語句賦值 for file in `ls /etc`
#!/bin/bash # 定義變量 name name="cizel" # 使用美圓 ($) 符號 echo $name # 使用美圓 ($) 符號和括號結合,經常使用於字符串拼接 echo ${name}
orvim
#!/bin/bash # 高級用法 # 默認值:若是變量沒有聲明,使用默認值 ${var=DEFAULT} echo ${name="ok"} # output: ok # 默認值:若是變量沒有聲明,或者爲空字符串,使用默認值 ${var:=DEFAULT} name="" echo ${name:="ok"} # output: ok
Shell 中的數字運算能夠採用 $((num1 + num2))
的方式,例如:bash
可能的坑:
- Shell 中的變量默認是字符串,使用
result=1+2;echo $result
, 輸出會是1+2
- 數值運算的兩個變量必須是
數字
或者數字字符串
, 否則會報錯
#!/bin/bash a=2 b="3" echo (($a + $b)) # output: 5 echo (($a - $b)) # output: -1 echo (($a * $b)) # output: 6 echo (($a / $b)) # output: 0 # 取模 / 求餘 echo $(($a % $b)) # output: 1 # 乘方 echo $(($a ** $b)) # output: 8 # 複雜運算 echo $(($a + ($a * $b))) # output: 8
Shell 的字符串與 PHP 的字符串相同,分爲 單引號字符串
和 雙引號字符串
#!/bin/bash $name="cizel" #單引號中變量和符號不會被解析 echo 'my name is ${name}' # output: my name is ${name} #雙引號中變量和符號會被解析 echo 'my name is ${name}' # output: my name is $shizhen
#!/bin/bash name="cizel" echo $name $name # output:cizel cizel
#!/bin/bash name="cizel" echo ${#name} # output: 5
#!/bin/bash name="my name is cizel" echo ${name:2} # output: name is cizel echo ${name:2:5} # output: name
${變量名#substring 正則表達式} 從字符串 開頭 開始配備 substring
, 刪除匹配上的表達式。
${變量名 %substring 正則表達式} 從字符串 結尾 開始配備 substring
, 刪除匹配上的表達式。
#!/bin/bash test="/home/work/.vimrc" echo ${test#/home} # output: /work/.vimrc
or
#!/bin/bash # 高級用法 test="/home/work/.vimrc" # 快速獲取文件名 echo ${test##*/} # output: .vimrc # 快速獲取路徑 echo ${test%/*} # output: /home/work
使用內置的字符串替換,會比 awk
, sed
, expr
的性能更好,
${變量 / 查找 / 替換值} 一個"/"表示替換第一個,"//"表示替換全部。
#!/bin/bash test="/home/work/.vimrc" echo ${test/.vimrc/.zshrc} # output: /home/work/.zshrc echo ${test/w*k/cizel} # output: /home/cizel/.vimrc
在 Shell 中,使用 test
來進行邏輯判斷。與其餘編程語言有許多不一樣,若是爲真返回 0
, 假返回 1
.
可能的坑:
- 邏輯判斷結果然返回
0
, 假返回1
- 使用
-gt
,-lt
,-ge
,-le
,-ne
,-eq
替換>
,<
,>=
,<=
,!=
,=
作數值比較- 與或非運算符使用
-a
,-o
,!
替換&
|
!
數值比較的運算符和彙編語言中相似,常見的 5 種數值比較以下:
符號 | 英文解釋 | 中文解釋 |
---|---|---|
-gt |
greater than | 大於 |
-lt |
less than | 小於 |
-ge |
greater equal | 大於等於 |
-le |
less equal | 小於等於 |
-ne |
not equal | 不等於 |
-eq |
equal | 等於 |
#!/bin/bash # 大於 test 3 -gt 2; echo $? # output: 0 # 小於 test 3 -lt 2; echo $? # output: 1 # 大於等於 test 3 -ge 2; echo $? # output: 0 # 小於等於 test 3 -le 2; echo $? # output: 1 # 不等於 test 3 -ne 2; echo $? # output: 0 # 等於 test 3 -eq 2; echo $? # output: 1
字符串比較的運算符以下表:
符號 | 解釋 |
---|---|
= |
字符串等於 |
!= |
字符串不等 |
-z |
判斷字符串長度是否爲零 |
-n |
判斷字符串長度是否大於零 |
#!/bin/bash # 字符串等於 test "my name is cizel" = "my name is cizel"; echo $? # output: 0 # 字符串不等 test "my name is cizel" = "my name is cz"; echo $? # output: 1 # 字符串長度判斷 test -z "my name is cizel"; echo $? # output: 1 test -n "my name is cizel"; echo $? # output: 0
符號 | 解釋 |
---|---|
-e |
判斷文件是否存在. |
-d |
判斷文件是否爲目錄. |
-f |
判斷文件是否爲常規文件. |
-L |
判斷文件是否爲符號連接. |
-r |
判斷文件是否可讀. |
-w |
判斷文件是否可寫. |
-x |
判斷文件是否可執行. |
#!/bin/bash ls -l # 當前目錄有以下文件,lib 文件夾,run.sh 文件,sh 符號連接,當前角色:work # drwxr-xr-x 1 work work 4096 Jun 28 2018 lib # -rwxr-xr-x 1 work work 2364 Jul 7 2018 run.sh # lrwxrwxrwx 1 root root 4 May 26 2014 sh -> bash # 判斷文件是否存在 test -e run.sh; echo $? # output: 0 # 判斷目錄是否存在 test -d lib; echo $? # output: 0 # 判斷文件是否爲常規文件 test -f run.sh; echo $? # output: 0 # 判斷文件是否爲符號連接 test -L sh; echo $? # output: 0 # 判斷文件是否爲符號連接 test -L sh; echo $? # output: 0 # 判斷文件是否可讀 / 寫 / 執行 (當前角色 work, 權限 rwx, 可讀可寫可執行) test -r run.sh; echo $? # output: 0 test -w run.sh; echo $? # output: 0 test -x run.sh; echo $? # output: 0
與其餘編程語言同樣,Shell 中也有與或非運算符。用於鏈接邏輯判斷條件,造成複合的邏輯判斷。
符號 | 英文解釋 | 中文解釋 |
---|---|---|
-a |
and | 與 |
-o |
or | 或 |
! |
-- | 非 |
#!/bin/bash # 與 test "1" = "1" -a "1" = "2"; echo $? # output: 1 # 或 test "1" = "1" -o "1" = "2"; echo $? # output: 0 #非 test ! "1" = "2"; echo $? # output: 0
Shell 中的選擇語句和其餘編程語言相似,支持 if, if-else, if-elif, if-elif-else, case-esac 常見的條件選擇方式
可能的坑:
- if 條件的左括號 (
[
) 後必須有一個空格,右括號前 (]
) 必須有一個空格。if [空格expression空格]- if, elif 後面都須要加
then
而後添加語句
#!/bin/bash var=`uname -s` if [ $var = "Linux" ]; then echo "Linux System" fi
#!/bin/bash var=`uname -s` if [ $var = "Linux" ]; then echo "Linux System" else echo "Other System" fi
#!/bin/bash var=`uname -s` if [ $var = "Linux" ]; then echo "Linux System" elif [ $var = "FreeBSD" ]; then echo "FreeBSD System" fi
#!/bin/bash var=`uname -s` if [ $var = "Linux" ]; then echo "Linux System" elif [ $var = "FreeBSD" ]; then echo "FreeBSD System" else echo "Other System" fi
case-esac 與經常使用的 switch-case 相似,能夠對比 if-elif-else 選擇食用
#!/bin/bash var=`uname -s` case $var in "Linux") echo "Linux System" ;; "FreeBSD") echo "FreeBSD System" ;; *) echo "Other System" ;; esac
常見的相似 c 語言的寫法
#!/bin/bash # 打印 1-10, 必須使用雙括號,使符號轉移 for ((i=1; i<=10; i++)); do echo $i done
in 的方法 (經常使用)
#!/bin/bash for i in {1..10}; do echo $i done
#!/bin/bash count=1 while [ $count -lt 3 ]; do echo $count count=$((count + 1)) done
直到條件爲真時,中止循環
#!/bin/bash count=1 until [ $count -eq 3 ]; do echo $count count=$((count + 1)) done
Shell 函數,使用 $1..$n 的方式接收參數
#!/bin/bash my_func() { echo "my function" echo "params 1: $1" echo "params 2: $2" echo "params 3: $3" } my_func 1 2 3
Shell 中使用 source
命令能夠加載其餘文件到當前 Shell 腳本中
# echo.sh echo() { command printf %s\\n "$*" 2>/dev/null }
#!/bin/bash source echo.sh echo 123