轉自http://blog.csdn.net/birdben/article/details/52157271
Shell腳本學習(一)Shell命令基礎
echo $SHELL
# $SHELL是一個環境變量,它記錄用戶所使用的Shell類型。你可以用命令:
Shell-name
# 來轉換到別的Shell,這裏Shell-name是你想要嘗試使用的Shell的名稱,如ash等。這個命令爲用戶又啓動了一個Shell,這個Shell在最初登錄的那個Shell之後,稱爲下級的Shell或子Shell。
exit
# 可以退出這個子Shell。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
先來個簡單的例子吧,也就是我們程序猿最長說的helloworld
helloworld.sh
#!/bin/bash
# 注意:"="號兩邊不能有空格,因爲個人習慣問題,我就總喜歡在等號兩邊加上空格
demo="hello world"
# 在終端輸出變量demo,也就是hello world
echo $demo
- 1
- 2
- 3
- 4
- 5
- 6
- 1
- 2
- 3
- 4
- 5
- 6
可以使用下面兩種方式執行helloworld.sh,執行sh腳本之前需要檢查權限問題,這裏就不細說Linux權限問題了,否則執行會提示沒有權限,具體請百度自行解決。
$ ./helloworld.sh
$ sh helloworld.sh
- 1
- 2
- 1
- 2
注意:這裏使用不同的操作系統執行Shell腳本時,可能會遇到問題。拿我自己舉例,我在Mac上能執行的Shell腳本可能在Ubuntu上無法執行,可能是因爲Mac默認使用bash執行的,而Ubuntu默認使用的是sh執行的。簡單一句話描述sh和bash的區別,sh是bash的“子集”,所以有的Shell腳本能用bash執行,而用sh執行就會報錯。
解決辦法
# 採用鏈接指向
$ ln -s /bin/bash /bin/sh
# 檢查是否正確
$ ls -l /bin/sh
- 1
- 2
- 3
- 4
- 1
- 2
- 3
- 4
sh和bash的具體區別請參考:
http://www.cnblogs.com/hopeworld/archive/2011/03/29/1998488.html
變量
Shell Script是一種弱類型語言,使用變量的時候無需首先聲明其類型。新的變量會在本地數據區分配內存進行存儲,這個變量歸當前的Shell所有,任何子進程都不能訪問本地變量。這些變量與環境變量不同,環境變量被存儲在另一內存區,叫做用戶環境區,這塊內存中的變量可以被子進程訪問。變量賦值的方式是:
variable_name = variable_value
如果對一個已經有值的變量賦值,新值將取代舊值。取值的時候要在變量名前加,variable_name可以在引號中使用,這一點和其他高級語言是明顯不同的。如果出現混淆的情況,可以使用花括號來區分,例如:
echo “Hi, $demos”
就不會輸出“Hi, hello worlds”,而是輸出“Hi,”。這是因爲Shell把demos當成一個變量,而demos未被賦值,其值爲空。正確的方法是:
echo “Hi, ${demo}s”
單引號中的變量不會進行變量替換操作。
關於變量,還需要知道幾個與其相關的Linux命令。
env用於顯示用戶環境區中的變量及其取值;set用於顯示本地數據區和用戶環境區中的變量及其取值;unset用於刪除指定變量當前的取值,該值將被指定爲NULL;export命令用於將本地數據區中的變量轉移到用戶環境區。
數組
#!/bin/bash
# 一對括號表示是數組,數組元素用“空格”符號分割開。
a=(1 2 3 4 5)
###### 獲取 ######
echo "獲取"
a=(1 2 3 4 5)
# 用${#數組名[@或*]} 可以得到數組長度
echo ${#a[@]}
echo ${#a[*]}
# 用${數組名[下標]} 可以得到指定下標的值,下標是從0開始
echo ${a[2]}
# 用${數組名[@或*]} 可以得到整個數組內容
echo ${a[@]}
echo ${a[*]}
###### 賦值 ######
echo "賦值"
a=(1 2 3 4 5)
# 直接通過 數組名[下標] 就可以對其進行引用賦值
a[1]=100
# 如果下標不存在,自動添加新一個數組元素
a[1000]=1000
echo ${a[*]}
echo ${#a[*]}
###### 刪除 ######
echo "刪除"
a=(1 2 3 4 5)
# unset 數組[下標] 可以清除相應的元素
unset a[1]
echo ${a[*]}
echo ${#a[*]}
# unset 數組[下標] 不帶下標,清除整個數據。
unset a
echo ${a[*]}
echo ${#a[*]}
###### 截取 ######
echo "截取"
a=(1 2 3 4 5)
# 截取數組 ${數組名[@或*]:起始位置:長度},從下標0開始,截取長度爲3,切片原先數組,返回是字符串,中間用“空格”分開
echo ${a[@]:0:3}
echo ${a[*]}
# 如果加上”()”,將得到切片數組,上面例子:c 就是一個新數據。
c=(${a[@]:1:4})
echo ${c[*]}
echo ${#c[*]}
###### 替換 ######
echo "替換"
a=(1 2 3 4 5)
# ${數組名[@或*]/查找字符/替換字符} 該操作不會改變原先數組內容,如果需要修改,可以看上面例子,重新定義數據。
echo ${a[@]/3/100}
echo ${a[@]}
# 如果需要需求,重新賦值給變量a
a=(${a[@]/3/100})
echo ${a[@]}
###### 根據分隔符拆分字符串爲數組 ######
echo "根據分隔符拆分字符串爲數組"
a="one,two,three,four"
# 要將$a按照","分割開,並且存入到新的數組中
OLD_IFS="$IFS"
IFS=","
arr=($a)
IFS="$OLD_IFS"
for s in ${arr[@]}
do
echo "$s"
done
# arr=($a)用於將字符串$a分割到數組$arr ${arr[0]} ${arr[1]} ... 分別存儲分割後的數組第1 2 ... 項 ,${arr[@]}存儲整個數組。變量$IFS存儲着分隔符,這裏我們將其設爲逗號 "," OLD_IFS用於備份默認的分隔符,使用完後將之恢復默認。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
if語句
if語句格式
if …; then
…
elif …; then
…
else
…
fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
與其他語言不同,Shell Script中if語句的條件部分要以分號來分隔。第三行中的[]表示條件測試,常用的條件測試有下面幾種:
# 要注意條件測試部分中的空格。在方括號的兩側都有空格,在-f、-lt、=等符號兩側同樣也有空格。如果沒有這些空格,Shell解釋腳本的時候就會出錯。
[ -f "$file" ] : 判斷$file是否是一個文件
[ -x "$file" ] : 判斷$file是否存在且有可執行權限,同樣-r測試文件可讀性
[ -n "$a" ] : 判斷變量$a是否有值
[ -z "$a" ] : 判斷變量$a是否爲空字符串
[ $a -lt 3 ] : 判斷$a的值是否小於3,同樣-gt和-le分別表示大於或小於等於
[ "$a" = "$b" ] : 判斷$a和$b的取值是否相等
[ cond1 -a cond2 ] : 判斷cond1和cond2是否同時成立,-o表示cond1和cond2有一成立
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
Shell邏輯運算符、邏輯表達式請參考:
if條件例子:
#!/bin/bash
# 打印終端命令行的所有參數
echo $*;
# 打印終端命令行的所有參數的個數
echo $#;
# 如果終端命令行的所有參數的個數小於3,就輸出所有參數
if [ $# -lt 3 ]; then
echo $*;
else
echo $0;
echo "參數過多不在控制檯顯示";
fi
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
在Shell中,腳本名稱本身是0,剩下的依次是0、1、2…、10、{11},等等。
- ∗:表示命令行的所有參數,不包括0,也就是說不包括文件名的參數列表
- # : 表示命令行參數的個數,不包括0,其實也可以理解成是包括$0的索引下標
for,while,until循環語句
while循環語句格式
while [ cond1 ] && { || } [ cond2 ] …; do
…
done
- 1
- 2
- 3
- 1
- 2
- 3
for循環語句格式
for var in …; do
…
done
for (( cond1; cond2; cond3 )) do
…
done
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 1
- 2
- 3
- 4
- 5
- 6
- 7
until循環語句格式
until [ cond1 ] && { || } [ cond2 ] …; do
…
done
- 1
- 2
- 3
- 1
- 2
- 3
循環例子:
#!/bin/bash
###### while循環例子1 ######
echo "while循環例子1";
i=10;
while [[ $i -gt 5 ]]; do
echo $i;
((i--));
done;
###### while循環例子2 ######
echo "while循環例子2";
# 循環讀取/etc/hosts文件內容
while read line; do
echo $line;
done < /etc/hosts;
###### for循環例子1 ######
echo "for循環例子1";
for((i=1;i<=10;i++)); do
echo $i;
done;
###### for循環例子2 ######
echo "for循環例子2";
# seq 10 產生 1 2 3 。。。。10空格分隔字符串。
for i in $(seq 10); do
echo $i;
done;
###### for循環例子3 ######
echo "for循環例子3";
# 根據終端輸入的文件名來檢查當前目錄該文件是否存在
for file in $*; do
if [ -f "$file" ]; then
echo "INFO: $file exists"
else
echo "ERROR: $file not exists"
fi
done;
###### until循環例子1 ######
echo "until循環例子1";
a=10;
until [[ $a -lt 0 ]]; do
echo $a;
((a--));
done;
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
case語句
case/esac語句格式
case var in
pattern 1 )
… ;;
pattern 2 )
… ;;
*)
… ;;
esac
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
#!/bin/bash
case $1 in
start | begin)
echo "start something"
;;
stop | end)
echo "stop something"
;;
*)
echo "Ignorant"
;;
esac
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
select交互語句
Bash提供了一種用於交互式應用的擴展select,用戶可以從一組不同的值中進行選擇。
select交互語句格式
select var in …; do
break;
done
- 1
- 2
- 3
- 1
- 2
- 3
例如,下面這段程序的輸出是:
#!/bin/bash
select ch in "begin" "end" "exit"; do
case $ch in
"begin")
echo "start something"
;;
"end")
echo "stop something"
;;
"exit")
echo "exit"
break;
;;
*)
echo "Ignorant"
;;
esac
done;
## 注意這裏交互輸入要輸入1,2,3,而不是beign,end,exit
# $ sh demo.sh
# 1) begin
# 2) end
# 3) exit
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
function語句
function語句格式
定義函數格式一:
functionname()
{
…
}
定義函數格式二:
# 函數名前面多了個function關鍵字
function functionname()
{
…
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
函數使用例子:
#!/bin/bash
###### 函數定義 ######
echo "函數定義";
# 注意:所有函數在使用前必須定義。這意味着必須將函數放在腳本開始部分,直至shell解釋器首次發現它時,纔可以使用。調用函數僅使用其函數名即可。
function hello() {
echo "Hello!";
}
function hello_param() {
echo "Hello $1 !";
}
###### 函數調用 ######
# 函數調用
echo "函數調用";
hello;
###### 參數傳遞 ######
echo "函數傳參調用";
hello_param ben;
###### 函數文件 ######
echo "函數文件調用";
# 調用函數文件,點和demo_call之間有個空格
. demo_call.sh;
# 調用函數
callFunction ben;
###### 載入和刪除 ######
echo "載入和刪除";
# 用unset functionname 取消載入
# unset callFunction;
# 因爲已經取消載入,所以會出錯
# callFunction ben;
###### 參數讀取 ######
echo "參數讀取";
# 參數讀取的方式和終端讀取參數的方式一樣
funWithParam(){
echo "The value of the first parameter is $1 !"
echo "The value of the second parameter is $2 !"
echo "The value of the tenth parameter is $10 !"
echo "The value of the tenth parameter is ${10} !"
echo "The value of the eleventh parameter is ${11} !"
echo "The amount of the parameters is $# !"
echo "The string of the parameters is $* !"
}
funWithParam 1 2 3 4 5 6 7 8 9 34 73
###### 函數return ######
echo "函數return";
funWithReturn(){
echo "The function is to get the sum of two numbers..."
echo -n "Input first number: "
read aNum
echo -n "Input another number: "
read anotherNum
echo "The two numbers are $aNum and $anotherNum !"
return $(($aNum+$anotherNum))
}
funWithReturn
# 函數返回值在調用該函數後通過 $? 來獲得
echo "The sum of two numbers is $? !"
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
函數文件demo_call.sh
#!/bin/bash
function callFunction() {
echo "callFunction $1 !";
return 1;
}
- 1
- 2
- 3
- 4
- 5
- 1
- 2
- 3
- 4
- 5
參考文章: