Shell 腳本入門及語法速查

[TOC]linux


1. Hello World

1.1. 基本結構

建立 helloWorld.sh 文件,寫入以下內容:git

#!/bin/bash

echo "hello world"

其中 #! 告訴系統其後路徑所指定的程序是解釋此腳本文件的 Shell 程序,常見的 Shell 程序有如下幾類(可經過命令 cat /etc/shells 查看):github

  • Bourne Shell(/usr/bin/sh或/bin/sh)
  • Bourne Again Shell(/bin/bash)
  • C Shell(/usr/bin/csh)
  • K Shell(/usr/bin/ksh)
  • Shell for Root(/sbin/sh)
  • ……

其中 Bash 在平常工做中被普遍使用,同時也是大多數 Linux 系統默認的 Shell。shell

執行該 sh 腳本數組

# 增長可執行權限
➜  chmod u+x helloWorld.sh

# 運行腳本
➜  ./helloWorld.sh
或
➜  sh hellowWorld.sh

1.2. 註釋

單行註釋bash

  • # 開頭的行是註釋

多行註釋ide

  • 方式一:用一對 {} 括起來,定義成一個函數,沒有地方調用即達到註釋的效果。函數

  • 方式二:測試

    :<<EOF
    註釋內容...
    註釋內容...
    註釋內容...
    EOF

2. 基本語法

2.1. 變量

  • 變量定義ui

    • 變量名建議大寫;
    • 有效字符僅能包含字母、數字、下劃線,首個字符不能以數字開頭;
    • = 兩邊不能有空格;
    • 不能使用標點符號;
    • 不能使用 bash 裏的關鍵字(可用 help 命令查看保留關鍵字)。

    以下示例:

    VAR1="whoru"
    VAR2=100
    var3=/data/www
    var4_name="root"
  • 訪問變量 $VAR1$(var1),其中,加花括號是爲了幫助解釋器識別變量的邊界。

  • 設置變量只讀 readonly VAR1

  • 刪除變量(不適用於只讀變量!unset VAR1

2.2. 字符串

  • 值用雙引號 "" 或單引號 '' 表示
    • 單引號單限制:
      • 單引號裏的任何字符都會原樣輸出;
      • 單引號字符串中的變量是無效的;
    • 雙引號的優勢:
      • 雙引號裏能夠有變量;
      • 雙引號裏能夠出現轉義字符;
  • 其它
    # 字符串拼接 
    name="xiaoming"
    var2="hello, "$name # 輸出 hello, xiaoming
    
    # 獲取字符串長度
    string="abcd"
    echo ${#string} # 輸出 4
    
    # 提取子字符串
    msg="zhangsan is a good man"
    echo ${msg:1:4} # 輸出 hang

2.3. 數組

  • bash 支持一維數組(不支持多維數組),而且沒有限定數組的大小。

  • 數組元素的下標由 0 開始,獲取數組元素要用到下標。

  • 定義:

    array1=(value0 value1 value2 value3)
    
    或
    
    array2[0]=value0
    array2[1]=value1
    array2[2]=value2
  • 讀取

    # 指定下標的元素
    echo ${array2[2]}; // 輸出 value2
    
    # 獲取數組全部元素
    echo ${array2[*]}; // 輸出 value0 value1 value2
    echo ${array2[@]}
  • 獲取數組元素個數

    echo ${#array2[@]}; // 輸出 3
    echo ${#array2[*]};
  • 取得數組中指定下標元素的字符長度

    echo ${#array2[2]};

2.4. 傳遞參數

在執行 Shell 腳本時,能夠向腳本傳遞參數,腳本內獲取參數的格式爲 $n,這裏的 n 指傳遞給腳本的第 n 個參數。

以下腳本文件 demo.sh

#!/bin/bash

echo "執行的文件名:$0";
echo "第一個參數爲:$1";
echo "第二個參數爲:$2";
echo "第三個參數爲:$3";

執行該文件,並傳遞參數,以下:

➜  ./demo3.sh param1 param2 param3
執行的文件名:./demo3.sh
第一個參數爲:param1
第二個參數爲:param2
第三個參數爲:param3

其中,$0 是一個特殊變量,表明當前腳本文件名,還有幾個相似的變量以下:

變量 說明
$# 傳遞給腳本的參數個數。
$* 以一個單字符串的形式顯示全部向腳本傳遞的參數,如 "$1 $2 ... $n"
$@ $* 相同,可是使用引號把每一個參數包裹起來,如 "$1" "$2" ... "$n"
$? 最後一個執行的命令的退出狀態:0 正常;1 或其它任何值,表示有錯誤
$$ 腳本運行的當前進程ID號
$! 最後一個後臺命令的進程號。

3. 運算符

3.1. 算數運算符

原生 bash 不支持簡單的數學運算,可是能夠經過其餘命令來實現,例如 awk 和 expr,其中 expr 最經常使用。

假定有兩個變量:a=10 b=20

運算符 說明 舉例
+ 加法 `expr $a + $b` 結果爲 30。
- 減法 `expr $a - $b` 結果爲 -10。
* 乘法 `expr $a \* $b` 結果爲 200。
/ 除法 `expr $b / $a` 結果爲 2。
% 取餘 `expr $b % $a` 結果爲 0。
= 賦值 a=$b 將把變量 b 的值賦給 a。
== 用於比較兩個數字是否相同 [ $a == $b ] 返回 false。
!= 用於比較兩個數字是否不相同 [ $a != $b ] 返回 true。

注意

  • 表達式和運算符之間要有空格,如 2+2 是錯誤的,必須寫成 2 + 2;
  • 完整的表達式要被反引號 ` ` 包裹起來;

3.2. 關係運算符

關係運算符只支持數字,不支持字符串,除非字符串的值是數字。

假定有兩個變量:a=10 b=20

運算符 說明 舉例
-eq 檢測兩個數是否相等 [ $a -eq $b ] 返回 false。
-ne 檢測兩個數是否不相等 [ $a -ne $b ] 返回 true。
-gt 檢測左邊的數是否大於右邊的 [ $a -gt $b ] 返回 false。
-lt 檢測左邊的數是否小於右邊的 [ $a -lt $b ] 返回 true。
-ge 檢測左邊的數是否大於等於右邊的 [ $a -ge $b ] 返回 false。
-le 檢測左邊的數是否小於等於右邊的 [ $a -le $b ] 返回 true。

3.3. 布爾操做符

假定有兩個變量:a=10 b=20

運算符 說明 舉例
! 非運算,表達式爲 true 則返回 false,不然返回 true。 [ ! false ] 返回 true。
-o 或運算,有一個表達式爲 true 則返回 true。 [ $a -lt 20 -o $b -gt 100 ] 返回 true。
-a 與運算,兩個表達式都爲 true 才返回 true。 [ $a -lt 20 -a $b -gt 100 ] 返回 false。

3.4. 邏輯運算符

假定有兩個變量:a=10 b=20

運算符 說明 舉例
&& 邏輯的 AND [[ $a -lt 100 && $b -gt 100 ]] 返回 false
|| 邏輯的 OR [[ $a -lt 100 || $b -gt 100 ]] 返回 true

3.5. 字符串運算符

假定有兩個變量:a="abc" b="efg"

運算符 說明 舉例
= 檢測兩個字符串是否相等 [ $a = $b ] 返回 false。
!= 檢測兩個字符串是否不相等 [ $a != $b ] 返回 true。
-z 檢測字符串長度是否爲 0(空) [ -z $a ] 返回 false。
-n 檢測字符串長度是否不爲0(非空) [ -n "$a" ] 返回 true。
str 檢測字符串是否爲不爲空 [ $a ] 返回 true。

3.6. 文件測試運算符

運算符 說明(若是是,則返回 true) 舉例
-b 檢測文件是不是塊設備文件 [ -b $file ]
-c 檢測文件是不是字符設備文件 [ -c $file ]
-d 檢測文件是不是目錄 [ -d $file ]
-f 檢測文件是不是普通文件(既不是目錄,也不是設備文件) [ -f $file ]
-g 檢測文件是否設置了 SGID 位 [ -g $file ]
-k 檢測文件是否設置了粘着位(Sticky Bit) [ -k $file ]
-p 檢測文件是不是有名管道 [ -p $file ]
-u 檢測文件是否設置了 SUID 位 [ -u $file ]
-r 檢測文件是否可讀 [ -r $file ]
-w 檢測文件是否可寫 [ -w $file ]
-x 檢測文件是否可執行 [ -x $file ]
-s 檢測文件是否爲非空(文件大小是否大於0)文件 [ -s $file ]
-e 檢測文件(包括目錄)是否存在 [ -e $file ]

4. 流程控制

4.1. if 語句

大多使用關係運算符檢查關係

# 語法格式
if condition1
then
    command1
    ...
elif condition2
then
    command2
else
    commandN
fi

4.2. case 語句

# 語法格式
case 值 in
    模式1)
        command1
        command2
        ...
        commandN
        ;;
    模式2)
        command1
        command2
        ...
        commandN
        ;;
    *)
        commandDefault
        ;;
esac

4.3. while 語句

用於不斷執行一系列命令,也用於從輸入文件中讀取數據;命令一般爲測試條件。其格式爲:

# 語法格式
while condition
do
    command
done

4.4. until 循環

執行一系列命令直至條件爲 true 時中止,它與 while 循環 在處理方式上恰好相反。

# 語法格式
until condition
do
    command
done

4.5. for 循環

# 語法格式
for var in item1 item2 ... itemN
do
    command1
    command2
    ...
    commandN
done

4.6. 無限循環

# 語法1
while :
do
    command
done

# 語法2
while true
do
    command
done

# 語法3
for (( ; ; ))

4.7. 退出循環

  • break 跳出整個循環,執行循環體後面的代碼,支持 break n 退出多層嵌套循環
  • continue 結束當前循環,一樣支持 continue n 退出多層

5. 輸入、輸出重定向

5.1. 命令列表

命令 說明
command > file 將輸出結果重定向到 file。
command < file 將輸入重定向到 file。
command >> file 將輸出以追加的方式重定向到 file。
n > file 將文件描述符爲 n 的文件重定向到 file。
n >> file 將文件描述符爲 n 的文件以追加的方式重定向到 file。
n >& m 將輸出文件 m 和 n 合併。
n <& m 將輸入文件 m 和 n 合併。
<< tag 將開始標記 tag 和結束標記 tag 之間的內容做爲輸入。

關於文件描述符:

  • 0 一般是標準輸入(STDIN),Unix程序默認從 stdin 讀取數據。
  • 1 標準輸出(STDOUT),Unix程序默認向 stdout 輸出數據。
  • 2 標準錯誤輸出(STDERR),Unix程序會向 stderr 流中寫入錯誤信息。

示例:

# 將 stdout 和 stderr 合併後重定向到 file
➜  command > file 2>&1

5.2. /dev/null 文件

這是一個特殊的文件,寫入到它的內容都會被丟棄;若是嘗試從該文件讀取內容,也什麼也讀不到。咱們一般將命令的輸出重定向到它,起到「禁止輸出」的效果。

如:

# 屏蔽 stdout 和 stderr
➜  command > /dev/null 2>&1

5.3. Here 文檔

# 將兩個 delimiter 之間的內容(document) 做爲輸入傳遞給 command。
command << delimiter
document
delimiter

說明:

  • 結尾的 delimiter 必定要頂格寫,前面不能有任何字符,後面也不能有任何字符,包括空格和 tab 縮進。
  • 開始的 delimiter 先後的空格會被忽略掉。

6. 函數

6.1. 基本語法

[ function ] funcName [()] {

    command;

    [return int;]

}

說明:

  • function 關鍵字非必須;
  • 若是該函數不傳入變量,這函數名的後面的括號能夠不加;
  • return 非必須;默認返回最後一條命令的執行結果;
  • 調用函數僅使用其函數名,如 funcName
  • 全部函數在使用前必須定義,即函數調用必需要在函數聲明以後。

6.2. 函數參數

func() {
    echo "第一個參數爲 $1 !"
    echo "第二個參數爲 $2 !"
    ...
    echo "第十個參數爲 ${10} !"
    ...
}

# 調用並傳參
func param1 param2 param3

說明

  • 在函數體內部,經過 $n 的形式來獲取參數的值,例如:$1 表示第一個參數,$2 表示第二個參數;
  • 當 n >= 10 時,須要使用 ${n} 來獲取參數。

7. 其它

7.1. echo 命令

用於字符串的輸出,基本格式 echo string

使用示例:

# 顯示普通字符
echo "It is a test" # 輸出 It is a test

# 顯示轉義字符
echo "\"It is a test\"" # 輸出 "It is a test"

# 顯示變量
#!/bin/sh
NAME="xiaoming" 
echo "$NAME It is a test" # 輸出 xiaoming is a test

# 顯示換行
echo -e "OK! \n" # -e 開啓轉義
echo "It is a test"

# 顯示不換行
echo -e "OK! \c" # -e 開啓轉義 \c 不換行
echo "It is a test"

# 顯示結果定向至文件
echo "It is a test" > myfile

# 顯示命令執行結果
echo `date`

7.2. printf 命令

模仿 C 程序庫(library)裏的 printf() 程序,主要用於格式化輸出。

默認 printf 不會像 echo 自動添加換行符,咱們能夠手動添加 \n

其基本語法格式爲:

printf  format-string  [arguments...]

說明:

  • format-string 爲格式控制字符串
  • arguments 爲參數列表。

示例:

➜  printf "%-10s %-8s %-4s\n" 姓名 性別 體重kg  
➜  printf "%-10s %-8s %-4.2f\n" 郭靖 男 66.1234 
➜  printf "%-10s %-8s %-4.2f\n" 楊過 男 48.6543 
➜  printf "%-10s %-8s %-4.2f\n" 郭芙 女 47.9876 
姓名     性別   體重kg
郭靖     男      66.12
楊過     男      48.65
郭芙     女      47.99

其中:

  • %s %c %d %f 都是格式替代符;
  • %-10s 指一個寬度爲10個字符(-表示左對齊,沒有則表示右對齊),任何字符都會被顯示在10個字符寬的字符內,若是不足則自動以空格填充,超過也會將內容所有顯示出來。
  • %-4.2f 指格式化爲小數,其中.2指保留2位小數。

更多使用示例:

# 沒有引號也能夠輸出
➜  printf %s abcdef

# 格式只指定了一個參數,但多出的參數仍然會按照該格式輸出,format-string 被重用
➜  printf %s abc def
abcdef

➜  printf "%s\n" abc def
abc
def

# 若是沒有 arguments,那麼 %s 用NULL代替,%d 用 0 代替
➜  printf "%s and %d \n" 
 and 0

7.3. test 命令

用於檢查某個條件是否成立,它能夠進行數值、字符和文件三個方面的測試(詳見第3節對應的運算符部分)。

基本使用示例:

cd /bin
if test -e ./bash
then
    echo '文件已存在!'
else
    echo '文件不存在!'
fi

7.4. 包含文件

被包含的文件不須要可執行權限。

# 方式一
. another_file.sh

# 方式二
source another_file.sh

更新:https://github.com/whorusq/linux-learning/edit/master/shell_basic_guide.md

相關文章
相關標籤/搜索