Linux Bash Shell學習(七):shell編程基礎——運行Shell指令碼、function

來源:互聯網
上載者:User

  本文也即《Learning the bash Shell》3rd Edition的第四章Basic Shell Programming之讀書筆記,但我們將不限於此。

運行shell指令碼程式

  一個包含shell命令的指令碼就是一個shell程式,例如.bash_profile。我們建立shell指令碼,允許的時候可以通過兩種方式:一、source

;二、只敲入檔案名稱,按斷行符號就可以執行,這種方式更為便捷。我們需要將檔案放置在命令搜尋路徑下(在Linux Bash學習(六):設定環境參數

中介紹),否則需要指出絕對路徑,例如在目前的目錄,使用./,

另外我們還需要將檔案的使用權限設定為可執行檔,採用$ chmod +x

的方式設定,+x表示增加執行的許可權。

  這兩種方式是由區別的。採用source就如同我們在terminal上敲入命令一樣。採用後一種方式,系統運行一個子進程,它copy了shell,叫作subshell,主shell等待子shell運行結束。另外我們設定讓子shell後台運行,即

&

  這個區別還體現在export

的使用上,例如我們設定aa=hello, world,這個變數在命令列中有效,但是在指令檔是無效,需要使用export aa='hello, world
'

來保證在subprocess中也是有效,即可以用於指令檔中。

函數Functions

  使用function有兩個原因:一、function存放在系統的記憶體,所以調用的使用,效率更高;二、更好地組織長的bash,使之模組化。定義function,有兩個方式:

function

functname

{

    shell commands

}

functname

( ){

    shell commands

}

  上面兩種方式沒有區別。我們可以通過unset –f functname

來刪除函數的定義。 當我們定義一個function,將它的名字和定義存放在記憶體,我們可以象調用shell指令碼的方式來調用它。我們通過declare -f

來查看當前已經定義的function情況,如果我們只查看function名字,使用declare -F

。我們可以在命令列中敲入一個function來檢驗,如果我們將function定義在一個檔案中,例如在檔案a,可以用source a

來是指生效,如果我們將a設定為可執行檔,這function的定義只在該指令碼中有效,如果需要使之仍然有效,保留環境,採用$.

./a

,而不只是$./a

Function作為一個整體運行,不會分割為子進程,此外Function的優先順序別高於指令碼。如果有重名,優先順序別依次如下:

  1. Aliases
  2. 關鍵字,例如function,if,for
  3. Functions
  4. Built-ins,例如cd,type
  5. 在命令搜尋路徑PATH下的指令碼和可執行檔

  如果我們需要查看所使用命令屬於哪種,用type name

,例如aa是個alias(表示pwd),同樣我們也定義了它作為一個function,根據優先順序別,aa優先作為alias,type aa,我們可以得到aa is aliased to ‘pwd’,可以用type –a(或者-all) name

,來查看aa代表的所有含義。如果使用非最優先順序別或者重新定義優先順序別的先後順序,在書的第7章,我們先放下此話題不表。上述的命令將顯示詳細內容,可以用type –t name

的方式,查看類型,將返回alias | keyword | function | builtin | file。type –p name

用於查看file的路徑,如果類型不是file將沒有返回,而type –P name

則強制尋找file的路徑。例如一個重名,它是一個alias,也是一個在PATH目錄下的可執行檔。-p則沒有返回,-P這返迴文件的絕對路徑。

位置參數

  在指令碼命令中,有時是帶有參數,這些參數可以通過位置變數來擷取。例如我們有個指令檔叫做test,執行的使用帶參數,即$./test param1 param2 param3,我們可以在指令碼中來擷取參數的值。使用$N,其中$0是./test,它表示執行的指令碼名字,剩餘的為所帶參數,$1為param1,$2為param2,如此類推,如果N大於實際參數的數目,為空白。我們一般將位置變數是從$1開始。

$*

表示所有參數組成的一個字串,在上面的例子中,為param1 param2 param3。這些參數之間的間隔是IFS的首個字母即空格,IFS包括TAB,空格,換行等字元。

$@

等同於"$1" "$2"... "$N"。

$#

表示參數的個數,在上面的例子中為3。

  這些位置變數都是唯讀,不能賦值的。$*和$@非常相似,一般而言輸出是一樣的。$*的分割是在IFS的字元,我們可以重新定義IFS的字元,將導致不同的輸出結果。我們在指令碼中定義IFS=,

,即可將輸出改用逗號做為分割,這個指令碼名字為a,運行./a h1 h2,則$#=2,表示有兩個參數,$@為h1 h2,$*為h1,h2

,輸出結果不一樣。

  同樣這些位置變數可以用於function中,並對function的參數進行體現,即是local的,屬於function,但是$0是例外,他表示指令碼的名字,這個參數是gobal的。下面是個例子。指令碼a內容如下:

hello ()

{

    var="hello";

    echo "Hello"

    echo "Hello: param num is $#"

    echo "Hello: $@"

    echo "Hello: $*"

    echo "Hello: $0 $1 $2"

    echo "Hello: var=$var";

}

var="hello";

echo "main: param num is $#"

echo "main: $@"

echo "main: $*"

echo "main: $0 $1 $2"

echo "main: var=$var";

hello h1 h2

 

  我們執行./a a1 a2 a3

main: param num is 3

main: a1 a2 a3

main: a1 a2 a3

main: ./a a1 a2

main: var=main

Hello

Hello: param num is 2

Hello: h1 h2

Hello: h1 h2

Hello: ./a h1 h2

Hello: var=hello

  除了$0外,所有的位置變數都是local的,即如果在function中,則在function中有效。同樣,使用者定義的其他變數,也是local的,即在最近的{}內有效。見上面例子中的使用者變數var。我們可以在function中定義var加上local來特別標明這是一個本地參數,上面的例子在函數hello,可以使用local var=”hello”

避免歧義的變數定義

  實際上我們使用$varname,是${varname}

的一個縮寫。有時我們不能使用縮寫,例如我們需要擷取第10個參數,使用$10,這實際是第一個參數加上“0”,需要使用${10}。又例如,我們希望顯示進程號,並在後面僅跟_、字母或者數字,我們使用echo $UID_,會見UID_看作一個整體,即echo ${UID_},因此是空,需要使用echo ${UID}_,假設進程號為1000,則為1000_。如果一個變數後面緊跟著_、字母或者數字,安全起見,需要用大括弧。

相關連結:
我的Linux操作相關文章

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在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.