shell腳本基礎

轉自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把demosdemos未被賦值,其值爲空。正確的方法是:

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 …; thenelif …; thenelsefi
  • 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中,腳本名稱本身是00、12…、10{11},等等。

  • :0,也就是說不包括文件名的參數列表
  • # : 表示命令行參數的個數,不包括0,其實也可以理解成是包括$0的索引下標

for,while,until循環語句

while循環語句格式

while [ cond1 ] && { || } [ cond2 ] …; dodone
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

for循環語句格式

for var in …; dodone

for (( cond1; cond2; cond3 )) dodone
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

until循環語句格式

until [ cond1 ] && { || } [ cond2 ] …; dodone
  • 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

參考文章:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章