文章目錄
- 1、Sha-Bang
- 2、“變量”
-
- 2.1 變量
- 2.2 運算
- 2.3 字元串
- 2.4 數組
- 3、流程控制
-
- 3.1 if 判斷
- 3.2 case 分支
- 3.3 for 循環
- 3.4 while 循環
- 3.5 until 循環
- 3.6 跳出循環
- 4、test指令
-
- 4.1 檔案判斷
- 4.2 數值比較
- 4.3 字元串測試
- 5、函數
-
- 5.1 定義與使用
- 5.2 函數參數
- 5.3 函數/程式傳回值
- 6、檔案
-
- 6.1 包含檔案
- 6.2 其他指令
- 7、重定向
-
- 7.1 輸出重定向
- 7.2 輸入重定向
- 8、管道
1、Sha-Bang
Sha-Bang是腳本開頭的兩個字元“
#!
”,腳本被讀取時根據這個特定的字元串識别出這是一個需要運作解析器的腳本,而具體使用哪個解析器就是根據後面的字元串來決定,通常腳本都是使用
#!/bin/bash
或
#!/bin/sh
來解析。但現在即使不指定,系統也能識别出并且正常運作腳本,不過還是推薦顯式地指定,因為即使機器能識别,我們也還是可以根據這個辨別一眼就能識别出這是一個shell腳本。
2、“變量”
2.1 變量
定義規則:
- 隻能英文字母、數字和下劃線,且首字母不能是數字;
- 不能使用空格、标點符号和shell的關鍵字;
有效的變量定義示例:
var
_var
var1
錯誤的示例:
va%r
2var
使用變量:
- 變量指派時“=”兩邊不能有空格,并且可以多次指派;
- 變量指派時全部以字元串形式解析,即便是單個數字;
- 使用時加上美元符“$”取值。
var="hello"
echo $var # 有效,輸出hello
echo ${var} # 有效,輸出hello,推薦使用“{}”可以劃定變量名稱範圍
echo $"var" # 無效,輸出var
echo $'var' # 無效,輸出var
echo $`var` # 無效,沒有var這個指令,且$符号為多餘
echo $(var) # 無效,沒有var這個指令
name="Mike"
echo "Hello, $name !" # 雙引号會解析變量:Hello, Mike !
echo 'Hello, $name !' # 單引号原樣輸出:Hello, $name !
設定變量隻讀:
ro_var="Mike"
readonly ro_var
ro_var="Amy" # 無法再次修改并提示
local(本地)變量:
#!/bin/bash
str="hello"
function func(){
local str="world"
echo "str: $str"
}
echo "str: $str" # hello
func # world
echo "str: $str" # hello
删除變量:
輸出的變量不能再次使用,并且不能删除readonly變量。
unset var
2.2 運算
進制:
格式:進制#數字
echo $((3#101)) # 輸出:10
echo $[5#100] # 輸出:25
運算:
a=1; b=3; c=5
echo $((a*b+c)) # 輸出:8
echo $[a*b+c] # 輸出:8
注: $(()) 和 $[] 效果一樣,但都不能單獨使用,必須立馬使用它的運算結果,否則認為是指令導緻報錯。另外,運算中的a/b/c可以直接使用,也可以加上“$”符号。
2.3 字元串
擷取字元串長度:
string="hello, world!"
echo ${#string} # 輸出:13
提取子字元串:
string="hello, world!"
echo ${string:0:5} # 輸出:hello
2.4 數組
array1=(Mike Green Amy)
array2=(
Mike
Green
Amy
)
array3[0]="Mike"
array3[10]="Amy" # 下标範圍沒有限制
echo ${array1[0]} # 輸出元素:Mike
echo ${array2[2]} # 輸出元素:Amy
echo ${#array3[0]} # 輸出單個元素長度:4
echo ${array1[@]} # 輸出數組所有元素:Mike Green Amy
echo ${array1[*]} # 輸出數組所有元素:Mike Green Amy
3、流程控制
3.1 if 判斷
情景1:單個if語句
if condition
then
# cmd...
fi
或
if condition; then
# cmd...
fi
情景2:if else-if else
if condition1; then
# cmd...
elif condition2; then
# cmd...
else
# cmd...
fi
注:“condition”判斷可以參考下一章的test指令使用。
3.2 case 分支
case "$var" in
"$val1") # 有無雙引号皆可
# cmd...
;;
val2 | val3) # 可以同時比對多個
# cmd...
;;
*)
# cmd...
;;
esac
3.3 for 循環
for var in item1 item2 ...
do
# cmd...
done
或
for var in item1 item2; do
# cmd...
done
3.4 while 循環
while condition
do
# cmd...
done
或
while condition; do
# cmd...
done
3.5 until 循環
一直執行一系列指令直到條件為true時推出,與while循環的處理方式剛好相反,一般情況while會優于until循環。
until condition
do
# cmd...
done
或
until condition; do
# cmd...
done
3.6 跳出循環
與C語言類似,也提供了以下2個跳出循環的關鍵字,并且作用一樣:
- continue:跳出本次循環,繼續判斷是否再次進入下一輪的循環
- break:跳出整個循環。
4、test指令
test指令(别名“
[
”)可以用于shell中檔案、數值、字元串三方面的條件測試,一般還提供内建結構“
[ ]
”,新版本bash還提供了“
[[ ]]
”,使用時需要注意測試表達式與test指令之間應有空格。
4.1 檔案判斷
條件 | 判斷說明 |
---|---|
-e/-a | 檔案是否存在 |
-d | 是否為目錄 |
-f | 是否為普通檔案 |
-b | 是否為塊裝置檔案 |
-c | 是否為字元裝置 |
-p | 是否為管道 |
-S | 是否為Socket |
-h/-L | 是否為符号連結 |
-r | 檔案是否可讀 |
-w | 檔案是否可寫 |
-x | 檔案是否可執行 |
示例:
#!/bin/bash
# test指令寫法1:
if test -e ~/.vimrc; then
echo "~/.vimrc is exist!"
fi
# test指令寫法2:
if [ -e ~/.vimrc ]; then
echo "~/.vimrc is exist!"
fi
4.2 數值比較
條件 | 說明 |
---|---|
-eq | 是否相等 |
-ne | 是否不等 |
-gt 或 > | 是否大于 |
-ge 或 >= | 是否大于等于 |
-lt 或 < | 是否小于 |
-le 或 <= | 是否小于等于 |
注:表格上“-gt 或 >”功能雖然相同,但使用方法不完全等效,詳情見示例。
示例:
#!/bin/bash
num1=12
num2=34
if [ "$num1" -lt "$num2" ];then
echo "num1 < num2"
fi
if(("$num1" < "$num2")); then
echo "num1 < num2"
fi
4.3 字元串測試
條件 | 說明 |
---|---|
=/== | 是否等于 |
!= | 是否不等 |
> | 根據ASCII順序判斷,在[]需要加上轉義字元“\” |
< | 根據ASCII順序判斷,在[]需要加上轉義字元“\” |
-z | 長度是否為0 |
-n | 長度是否不為0 |
示例:
#!/bin/bash
str1="hello"
str2="Hello"
if [ $str1 = $str2 ]; then
echo "str1 == str2"
else
echo "str1 != str2"
fi
5、函數
5.1 定義與使用
形式1:使用function關鍵字定義
function func_name(){
# cmd...
}
形式2:與C語言類似
func_name(){
# cmd...
}
注:bash不像C語言一樣可以聲明函數,是以應該在調用函數之前先定義好,在調用函數時直接使用函數名即可,如:
#!/bin/bash
func(){
echo "I'm in func!"
}
echo "before call func!"
func
echo "after call func!"
5.2 函數參數
參數 | 說明 |
---|---|
$0、$1… | 指令行參數,類比于C語言的argv[0]、argv[1]… |
$# | 指令行參數個數,類比于C語言的argc |
$* | 指令行所有參數作為一個整體,引用時需加雙引号"" |
[email protected] | 指令行所有參數,但每個都是一個獨立的字元串,引用時也需加雙引号"" |
5.3 函數/程式傳回值
符号 | 說明 |
---|---|
$? | 擷取上次函數/程式退出的狀态;成功傳回0,失敗傳回1。 (隻能檢視一次,因為使用echo等指令後又會被替換為該指令的傳回值) |
6、檔案
6.1 包含檔案
包含其他檔案可以讓編寫腳本時減少編寫重複的代碼,友善開發。指令格式如下:
. otherfile
source otherfile
示例:
ip.conf
test.sh
#!/bin/bash
source ./ip.conf
echo "IP address: ${ip}"
注:被包含的檔案可以不具備可執行權限。
6.2 其他指令
指令 | 說明 | 示例 |
---|---|---|
realpath | 檢視檔案的絕對路徑,多用于檢視軟連結檔案的真實檔案 | realpath file.txt |
dirname | 去除檔案名中的非目錄部分,多用于檢視檔案所在路徑 | dirname /home/book/… |
7、重定向
7.1 輸出重定向
指令 | 說明 |
---|---|
cmd > file | 将cmd指令的輸出寫到file中 |
cmd >> file | 将cmd指令的輸出追加到file中 |
cmd > file 2>&1 | 将cmd指令的标準錯誤(stderr描述符為2)也重定向到标準輸出并重定向到檔案file中 |
cmd > /dev/null | 将cmd指令的輸出丢棄(/dev/null類似于一個黑洞) |
7.2 輸入重定向
指令 | 說明 |
---|---|
cmd < file | 原本由鍵盤輸入的更改為file檔案輸入 |
8、管道
|
是管道的符号,它将前一個指令的輸出作為下一個指令的輸入。一般左右兩邊是不同的2個程序,部分指令需要前面加上
xargs
将管道或标準輸入資料轉換成指令行參數。例如:
dmesg | grep "USB"
find ./ -name *.conf | xargs ls -l