Linux下的Shell編程

    從程序員的角度來看, Shell自己是一種用C語言編寫的程序,從用戶的角度來看,Shell是用戶與Linux操做系統溝通的橋樑。用戶既能夠輸入命令執行,又能夠利用 Shell腳本編程,完成更加複雜的操做。在Linux GUI日益完善的今天,在系統管理等領域,Shell編程仍然起着不可忽視的做用。深刻地瞭解和熟練地掌握Shell編程,是每個Linux用戶的必修 功課之一。
    Linux的Shell種類衆多,常見的有:Bourne Shell(/usr/bin/sh或/bin/sh)、Bourne Again Shell(/bin/bash)、C Shell(/usr/bin/csh)、K Shell(/usr/bin/ksh)、Shell for Root(/sbin/sh),等等。不一樣的Shell語言的語法有所不一樣,因此不能交換使用。每種Shell都有其特點之處,基本上,掌握其中任何一種 就足夠了。在本文中,咱們關注的重點是Bash,也就是Bourne Again Shell,因爲易用和免費,Bash在平常工做中被普遍使用;同時,Bash也是大多數Linux系統默認的Shell。在通常狀況下,人們並不區分 Bourne Shell和Bourne Again Shell,因此,在下面的文字中,咱們能夠看到#!/bin/sh,它一樣也能夠改成#!/bin/bash。
    利用vi等文本編輯器編寫Shell腳本的格式是固定的,以下:html

  •  #!/bin/sh
  •  #comments
  •  Your commands go here

    首行中的符號#!告訴系統其後路徑所指定的程序便是解釋此腳本文件的Shell程序。若是首行沒有這句話,在執行腳本文件的時候,將會出現錯誤。後續的部分就是主程序,Shell腳本像高級語言同樣,也有變量賦值,也有控制語句。除第 一行外,以#開頭的行就是註釋行,直到此行的結束。若是一行未完成,能夠在行尾加上",這個符號代表下一行與此行會合併爲同一行。
    編輯完畢,將腳本存盤爲filename.sh,文件名後綴sh代表這是一個Bash腳本文件。執行腳本的時候,要先將腳本文件的屬性改成可執行的:
    chmod +x filename.sh
    執行腳本的方法是:
    ./filename.sh

    下面咱們從經典的「hello world」入手,看一看最簡單的Shell腳本的模樣。程序員

  • #!/bin/sh
  • #print hello world in the console window
  • a = "hello world"
  • echo $a

    Shell Script是一種弱類型語言,使用變量的時候無需首先聲明其類型。新的變量會在本地數據區分配內存進行存儲,這個變量歸當前的Shell全部,任何子進程都不能訪問本地變量。這些變量與環境變量不一樣,環境變量被存儲在另外一內存區,叫作用戶環境區,這塊內存中的變量能夠被子進程訪問。變量賦值的方式是:
    variable_name = variable_value
    若是對一個已經有值的變量賦值,新值將取代舊值。取值的時候要在變量名前加$,$variable_name能夠在引號中使用,這一點和其餘高級語言是明顯不一樣的。若是出現混淆的狀況,可使用花括號來區分,例如:
    echo "Hi, $as"
    就不會輸出「Hi, hello worlds」,而是輸出「Hi,」。這是由於Shell把$as當成一個變量,而$as未被賦值,其值爲空。正確的方法是:
    echo "Hi, ${a}s"
    單引號中的變量不會進行變量替換操做。

關於變量,還須要知道幾個與其相關的Linux命令。正則表達式

  • env用於顯示用戶環境區中的變量及其取值;
  • set用於顯示本地數據區和用戶環境區中的變量及其取值;
  • unset用於刪除指定變量當前的取值,該值將被指定爲NULL;
  • export命令用於將本地數據區中的變量轉移到用戶環境區。

下面咱們來看一個更復雜的例子,結合這個例子,咱們來說述Shell Script的語法。shell

  1. #!/bin/bash
  2. # we have less than 3 arguments. Print the help text:
  3. if [ $# -lt 3 ]; then
  4. cat<<HELP
  5.      ren -- renames a number of files using sed regular expressions
  6.      USAGE: ren 'regexp' 'replacement' files
  7.      EXAMPLE: rename all *.HTM files in *.html:
  8.      ren 'HTM$' 'html' *.HTM
  9. HELP
  10.      exit 0
  11. fi
  12. OLD="$1"
  13. NEW="$2"
  14. # The shift command removes one argument from the list of
  15. # command line arguments.
  16. shift
  17. shift
  18. # $* contains now all the files:
  19. for file in $*; do
  20. if [ -f "$file" ]; then
  21.     newfile=`echo "$file" | sed  "s/${OLD}/${NEW}/g"`
  22.         if [ -f "$newfile" ]; then
  23.             echo "ERROR: $newfile exists already"
  24.         else
  25.             echo "renaming $file to $newfile "
  26.             mv "$file" "$newfile"
  27.         fi
  28. fi
  29. done

咱們從頭來看,前面兩行上一個例子中已經解釋過了,從第三行開始,有新的內容。if語句和其餘編程語言類似,都是流程控制語句。它的語法是:

if …; then

elif …; then

else

fi

與其餘語言不一樣,Shell Script中if語句的條件部分要以分號來分隔。第三行中的[]表示條件測試,經常使用的條件測試有下面幾種:express

  • [ -f "$file" ]  判斷$file是不是一個文件
  • [ $a -lt 3 ]    判斷$a的值是否小於3,一樣-gt和-le分別表示大於或小於等於
  • [ -x "$file" ]  判斷$file是否存在且有可執行權限,一樣-r測試文件可讀性
  • [ -n "$a" ]     判斷變量$a是否有值,測試空串用-z
  • [ "$a" = "$b" ]     判斷$a和$b的取值是否相等
  • [ cond1 -a cond2 ]  判斷cond1和cond2是否同時成立,-o表示cond1和cond2有一成立

要注意條件測試部分中的空格。在方括號的兩側都有空格,在-f、-lt、=等符號兩側一樣也有空格。若是沒有這些空格,Shell解釋腳本的時候就會出錯。

    $#表示包括$0在內的命令行參數的個數。

    在Shell中,腳本名稱自己是$0,剩下的依次是$0、$一、$2…、${10}、${11},等等。$*表示整個參數列表,不包括$0,也就是說不包括文件名的參數列表。
    如今咱們明白第三行的含義是若是腳本文件的參數少於三個,則執行if和fi語句之間 的內容。而後,從第四行到第十一行之間的內容在Shell Script編程中被稱爲Here文檔,Here文檔用於將多行文本傳遞給某一命令。Here文檔的格式是以<<開始,後跟一個字符串,在 Here文檔結束的時候,這個字符串一樣也要出現,表示文檔結束。在本例中,Here文檔被輸出給cat命令,也即將文檔內容打印在屏幕上,起到顯示幫助 信息的做用。
    第十二行的exit是Linux的命令,表示退出當前進程。在Shell腳本中可使用全部的Linux命令,利用上面的cat和exit,從一方面來講,熟練使用Linux命令也能夠大大減小Shell腳本的長度。
    十4、十五兩句是賦值語句,分別將第一和第二參數賦值給變量OLD和NEW。緊接下來的兩句是註釋,註釋下面的兩條shift的做用是將參數列表中的第一個和第二個參數刪除,後面的參數依次變爲新的第一和第二參數,注意參數列表本來也不包括$0。
    而後,自二十一行到三十一行是一個循環語句。

Shell Script中的循環有下面幾種格式:編程

  • while [ cond1 ] && { || } [ cond2 ] …; do
  • done

 

  • for var in …; do
  • done

 

  • for (( cond1; cond2; cond3 )) do
  • done

 

  • until [ cond1 ] && { || } [ cond2 ] …; do
  • done


    在上面這些循環中,也可使用相似C語言中的break和continue語句中斷 當前的循環操做。第二十一行的循環是將參數列表中的參數一個一個地放入變量file中。而後進入循環,判斷file是否爲一個文件,若是是文件的話,則用 sed命令搜索和生成新的文件名。sed基本上能夠當作一個查找替換程序,從標準輸入,例如管道讀入文本,並將結果輸出到標準輸出,sed使用正則表達式 進行搜索。在第二十三行中,backtick(`)的做用是取出兩個backtick之間的命令輸出結果,在這裏,也就是將結果取出賦給變量 newfile。此後,判斷newfile是否已經存在,不然就把file改爲newfile。這樣咱們就明白這個腳本的做用了,Shell Script編寫的其餘腳本與此類似,只不過是語法和用法稍有不一樣而已。

    經過這個例子咱們明白了Shell Script的編寫規則,但還有幾件事情須要講述一下。
1、除了if語句以外,Shell Script中也有相似C語言中多分支結構的case語句,它的語法是:bash

  • case var in
  • pattern 1 )
  • … ;;
  • pattern 2 )
  • … ;;
  • *)
  • … ;;
  • esac

咱們再就下面一個例子,看看case語句的用法。less

  • while getopts vc: OPTION
  • do
  • case $OPTION in
  • c) COPIES=$OPTARG
  •      ehco "$COPIES";;
  • v) echo "suyang";;
  • \?) exit 1;;
  • esac
  • done

上面的getopts相似於C語言提供的函數getopts,在Shell Script中,getopts常常和while語句聯合起來使用。getopts的語法以下:
    getopts option_string variable
    option_string中包含一串單字符選項,若getopts在命令行參數中發現了連字符,那麼它會將連字符以後的字符與option_string進行比較,若匹配成功,則把變量variable的值設爲該選項,若無匹配,則把 變量的值設爲?。有時候,選項還會帶一個值,例如-c5等,這時要在option_string中該選項字母后面加上一個冒號,getopts發現冒號 後,會讀取該值,而後將該值放入特殊變量OPTARG中。這個命令比較複雜,若有須要,讀者能夠詳細參閱Shell編寫的相關資料。

上面這個循環的做用就是依次取出腳本名稱後面的選項,進行處理,若是輸入了非法選項,則進入"?指定的部分,退出腳本程序。

2、Bash提供了一種用於交互式應用的擴展select,用戶能夠從一組不一樣的值中進行選擇。其語法以下:編程語言

  • select var in …; do
  • break;
  • done

例如,下面這段程序的輸出是:

#!/bin/bash
echo "Your choice?"
select var in "a" "b" "c"; do
break
done
echo $var
----------------------------
Your choice?
1) a
2) b
3) c

3、Shell Script中也可使用自定義的函數,其語法形式以下:

編輯器

  • functionname()
  • {
  • }

       例如咱們能夠把上面第二個例子中第四到第十二行放入一個名爲help函數體內,之後每次調用的時候直接寫help便可。函數中處理函數調用參數的方法是,直接用上面講過的$一、$2來分別表示第1、第二個參數,用$*表示參數列表。

4、咱們也能夠在Shell下調試Shell Script腳本,固然最簡單的方法就是用echo輸出查看變量取值了。Bash也提供了真正的調試方法,就是執行腳本的時候用-x參數。
    sh ?x filename.sh
這會執行腳本並顯示腳本中全部變量的取值,也可使用參數-n,它並不執行腳本,只是返回全部的語法錯誤。

 

shell文件中獲取當前時間  mytime=`date -d '1 day ago' "+%Y%m%d%k%M%S"` echo "$mytime"

 

轉自:http://www.cnblogs.com/suyang/archive/2008/05/18/1201990.html

相關文章
相關標籤/搜索