SHELL入門教程(7)-編寫指令碼

來源:互聯網
上載者:User

shell入門教程(1)-shell基礎 - justkk的專欄 - 部落格頻道 - CSDN.NET
http://blog.csdn.net/justkk/article/details/43795131

shell入門教程(2)-變數和參數 - justkk的專欄 - 部落格頻道 - CSDN.NET
http://blog.csdn.net/justkk/article/details/44081993

shell入門教程(3)-命令編輯 - justkk的專欄 - 部落格頻道 - CSDN.NET
http://blog.csdn.net/justkk/article/details/44617445

shell入門教程(4)-作業控制 - justkk的專欄 - 部落格頻道 - CSDN.NET
http://blog.csdn.net/justkk/article/details/46801163

SHELL入門教程(5)-算術運算 - justkk的專欄 - 部落格頻道 - CSDN.NET
http://blog.csdn.net/justkk/article/details/47025297

SHELL入門教程(6)-環境 - justkk的專欄 - 部落格頻道 - CSDN.NET
http://blog.csdn.net/justkk/article/details/47025321

SHELL入門教程(7)-編寫指令碼 - justkk的專欄 - 部落格頻道 - CSDN.NET
http://blog.csdn.net/justkk/article/details/47025397

 

 

1、執行指令碼

SHELL也是一個高層程式設計語言,SHELL程式通常稱為指令碼,是解釋執行的,不需要編譯。

指令碼的執行需要讀取r與執行x許可權,可以通過chmod命令添加相應的許可權,ls -l查看許可權。

ls -l 0.sh

-rwxr-xr-x. 1 root root 10 Jul 8 14:59 0.sh

可以直接通過指令碼名稱執行,如:0.sh,此時需要讀取與執行許可權。

也可以使用bash執行,如:bash 0.sh,此時只需要讀取許可權。

通常,SHELL指令碼是在一個單獨環境中執行:

1、當前SHELL中的變數需要export之後才能在指令碼中使用

2、另外,指令碼不會改變當前SHELL環境。

 

2、位置參數

位置參數是一組特殊變數,用來跟蹤指令碼的參數,其名稱只包含數字,如:

$0 表示指令碼名稱本身,剩餘的$1 $2 ..依次表示指令碼的參數

可以使用下面的指令碼驗證:

echo "Script name:  $0"

echo "Number of args passed: $#"

echo "Arguments passed:  $*"

echo "Arg 1=$1,Arg 2=$2, Arg 3=$3"

儲存為 0.sh,執行./0.sh a b c

特殊的變數:

$# 表示參數數目,$*與 $@ 表示所有的參數。

$* 與 $@的區別:$* 把所有參數作為一個整體,而$@表示分離的個體。不帶雙引號時,兩者效果相同。

 

位置參數不能直接使用var=value的方式修改,可以使用shift 命令。

shift 命令依次向左移動所有的參數,每個參數替代目標位置上的參數,同時參數的數目相應減少。

預設移動一個,可以指定參數,表示移動的數目,如 shift 2

可以使用下面的指令碼驗證:

echo "Number of args passed: $#"

echo "Arguments passed:  $*"

echo "Arg 1=$1,Arg 2=$2, Arg 3=$3"

shift

echo "Number of args passed: $#"

echo "Arguments passed:  $*"

echo "Arg 1=$1,Arg 2=$2, Arg 3=$3"

儲存為 0.sh,執行./0.sh a b c

3、exit

exit 命令退出指令碼的執行,後續的命令不再執行。

可以附帶一個參數,用來表示整個指令碼的退出狀態,即執行結果。

如:

echo "over"

exit 1

儲存為 0.sh,執行./0.sh

之後在 SHELL 中查看指令碼的退出狀態,echo $?

4、[[..]] 命令

這個命令用來執行條件判斷,可以檢查檔案屬性、字串、模式、整數等。

格式為 [[ expression ]],注意[[ 後面以及 ]] 前面都需要空格,操作符兩邊也需要空格。樣本:

[[ $a = 3 ]] && echo "a is 3"

c=hi; [[ $c = h* ]] && echo "begin with h"

a=4; [[ $a = +([0-9]) ]] && echo "a number"

字串操作符

-n string  true if length of string is not zero

-o option  true if option is set

-z string  true if length of string is zero

string1 = string2  true if string1 is equal to string2

string1 != string2  true if string1 is not equal to string2

string = pattern  true if string matches pattern

string != pattern  true if string does not match pattern

string1 < string2  true if string1 less than string2

string1 > string2  true if string1 greater than string2

具體用法參見 man test

 

注意整數的比較,使用-gt -lt等,不能使用大於或小於,那是用來比較字串的

[[ 13 > 2 ]] && echo "13>2"

[[ 13 -gt 2 ]] && echo "13 greater than 2"

其實整數的比較可以使用((..))命令,更方便,其中的變數不用添加$,也不需要空格,如:

a=13;((a>2))&&echo ">2"

一點注意,兩個整數的相等比較,在((..))內部需要使用==,而不是=。單個等號的含義是賦值。

在[[..]]內部可以使用==或單個等號來比較。

與C語言類似,!表示邏輯 NOT。&&表示並且,||表示或者。()用來改變運算式優先順序。

(((3+2)*4==20))&&echo "20"

 

test或[..]也可以用來執行條件判斷,他們同樣是SHELL的內建命令。如:

test 1 -eq 1 && echo "ok"

[ 1 -eq 1 ] && echo "ok"

與他們相比,推薦使用[[..]]

總結:

1、整數的比較操作使用((..)),其他的比較操作使用[[..]]

2、使用雙等號==判斷兩個運算元是否相等

5、控制命令 • case 執行多個分支檢測,如:

case $1 in

a) echo "a";;

b) echo "b";;

*) echo "other";;

esac • for 命令執行迴圈

for i in 1 2 3

do

        echo $i

done

或者,此時迴圈變數依次從所有的位置參數取值

for i

do

        echo $i

done

或者,

for((i=1;i<10;i++))

do

        echo $i

done • if ,如:

a=7

if ((a>10));then

        echo "a>10"

elif ((a>5));then

        echo "a>5"

else

        echo "a<=5"

fi • while ,如:

a=1

while((a<10))

do

        echo $a

        ((a++))

done • until ,如:

a=1

until((a==10))

do

        echo $a

        ((a++))

done • break 跳出迴圈, continue 繼續迴圈

其參數指定迴圈的層次,預設為1

如:break 2 跳出2層迴圈

  • select ,用來顯示一個簡單的菜單,並等待使用者的選擇,如:

select i in Choice-A Choice-B Choice-C

do

      echo "You picked selection $REPLY: $i"

done

觀察輸出結果,顯示了SHELL的第三個命令列提示符PS3,其預設值是#?,可以修改並查看效果。

順便說一下最後一個命令列提示符PS4,這是跟蹤調試提示符,預設值是+,當開啟SHELL的跟蹤選項時,每個執行的命令及其參數都會先行顯示,行首添加PS4 的值。 • 關於注釋

# 之後直到行尾的內容都作為注釋,而不會被SHELL解釋執行。

特別注意,指令碼第一行的頂頭的#! 不是注釋,它後面可以指定一個執行程式,表示整個指令碼由那個執行程式解釋執行。如:

#!/usr/bin/awk -f

{print $0}

6、輸入輸出命令 • echo  輸出資訊,支援逸出字元

\a  bell character

\b  backspace

\c  line without ending newline (remaining arguments ignored)

\f  formfeed

\n  newline

\r  return

\t  tab

\v  vertical tab

\\  backslash

\0x  8-bit character whose ASCII code is the 1-, 2-, or 3-digit octal number x

注意,使用逸出字元時需要使用-e選項,如:

echo -e "\044"

echo -e "a\tb\ncd"

  • exec  I/O 重新導向,使用檔案描述符 0-9 ,如:

exec 5>&1  # 複製檔案描述符,此時5等價於1,都對應螢幕

echo a>&5  # 寫入描述符5,實際輸出到螢幕

exec 1>ff.out  # 重新導向描述符1,指向檔案ff.out

echo b  # 輸出到檔案ff.out

exec 1>&5  # 再次重新導向描述符1,指向描述符5,對應螢幕

echo c  # 輸出到螢幕

exec 1>&-  # 關閉描述符1

echo d  # 報錯,因為輸出已關閉

  • read  讀取輸入內容,存入變數,如:

read a  # 等待鍵盤輸入,輸入內容放入變數a

read a b  # 等待鍵盤輸入,拆分後放入變數a,b,分隔字元通常是空白符,如空格、<TAB> • IFS 變數,用以指定輸入內容的分隔字元,如: IFS=,

之後輸入內容採用逗號分隔,read a b,如果輸入1,2,那麼變數a和b分別取值1和2。 • read 命令預設從標準輸入(即描述符 0 )讀取內容,可以通過 -u 選項指定從其他描述符讀取,如:

exec 4<ff.out

read -u4 b • REPLY 變數

如果read命令沒有指定任何變數,讀取內容將放入變數REPLY,如:

read; echo $REPLY

  • read 命令的一個 陷阱 ,查看下面的情境:

unset b c

A="3 4"

echo $A|read b c

echo $b,$c

希望變數b和c分別取值3和4,實際驗證結果:變數b和c什麼也沒有。

究其原因,read命令是在子SHELL中執行的,雖然在子SHELL中讀到了3和4,但是不會影響當前SHELL。

修改:

unset b c

A="3 4"

read b c <<!

$A

!

echo $b,$c

 

8、其他 • . 命令, source 命令,兩者等價,在當前 SHELL 中執行參數指定的指令碼, 改變當前的 SHELL 環境

通常用來讀取並執行一個環境定義檔案,假定檔案0.sh的內容如下:

A=3

B=4

比較兩種執行方式:./0.sh 與 . ./0.sh • 函數,定義形式如下,其中關鍵字 function 可以省略:

function aa()

{

  echo aa

}

函數定義之後,其調用方式與參數傳遞方式與普通命令類似,同樣可以使用$?檢查其退出狀態。

aa()

{

        echo hh

        return 1

}

aa  # 調用時可以給函數傳遞參數,函數內部需要使用位置參數訪問

echo $?

  • 預設情況下當前 SHELL 中定義的函數在子 SHELL 中不可用,需要匯出: export -f aa • 預設情況下,函數中的變數和調用者是共用的

調用前定義的變數可以在函數中使用,函數中定義的變數在調用結束後依然可見,函數內部定義局部變數時可以使用 local 關鍵字。

A=1

function aa

{

        local A=3

        B=2

        echo "in function: $A,$B"

}

aa

echo $A,$B • 查看已經定義的函數

使用typeset -F -p 或 typeset -f -p,前者只顯示函數名稱,後者同時顯示函數的定義。

  • trap 命令,用來捕獲訊號,並執行對應的動作,如:

trap 'echo nono' 2  # 捕獲中斷訊號

trap "" 2  # 忽略中斷訊號

trap 2  # 恢複中斷訊號的預設處理

特殊的訊號0,表示指令碼退出。可以捕獲這個訊號,在指令碼退出時執行一些清理動作。

trap 'echo over' 0

..

  • 調試指令碼

幾個有用的選項:

-n  唯讀入指令碼,並不實際執行,只檢查文法

-v  讀入指令碼時顯示讀入的程式碼

-x  執行時顯示每個命令及其參數

如:sh -x 0.sh

可以定製 -x 選項顯示的提示符,如:export PS4='[$LINENO] ‘

之後將顯示每個命令所在的行號

trap 命令也可以用來調試指令碼,使用特殊的訊號,如:DEBUG、ERR

trap 'echo error at line $LINENO' ERR

trap 'echo debug line=$LINENO' DEBUG

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.