shell(bash)學習筆記

來源:互聯網
上載者:User

以前只是簡單看過一些文章,瞭解一些。平時也就是寫個簡單的命令組合啥的,沒寫過複雜的指令碼。最近一次為了恢複資料,寫了一下指令碼,發現這東西光學不練確實不行。順便記一下學習筆記備用。

約定:本文中的shell特指bash.

由於javaeye部落格編輯器沒有提供shell代碼格式,就只好勉強用javascript指令碼格式插入代碼。

一.變數

變數直接賦值,不用提前聲明。

Js代碼
  1. var="Hello"  
  2. var=Hello   
  3. var='Hello'  
var="Hello"var=Hellovar='Hello'

 

注意幾點:

1.變數和值之間不能有空格,否則解譯器會認為是幾個命令。很多程式員的習慣是在=號兩邊留空格為了好看,但這點在shell中行不通。

2.字串不必用"號或者',上面的幾種賦值方式是等價的。除非字串之間有空格的時候。

如:

Js代碼
  1. var="Hello World"  
var="Hello World"

 

這時候就需要用引號。

3.

Js代碼
  1. var=  
var=

 這樣的語句也是合法的,表示var的值為空白。

 

4.使用變數的時候需要在變數前面加上$符號。這一點php程式員比較熟悉。

如:

Js代碼
  1. echo $var  
echo $var

 

這也就是為什麼shell中的字串不必用引號的原因。你如果直接運行

Js代碼
  1. echo var  
echo var

 

系統會將var當作字串,而不是變數處理。在變數前加上$號還有個好處就是在字串中輸出變數的時候,直接在字串裡面用變數就行。

如:

Js代碼

  1. var=World   
  2. var2="$var World"  
  3. echo $var2  
var=Worldvar2="$var World"echo $var2

 

 

但與php不同的是變數賦值的時候不用加$符號。因為shell中沒有==這個符號,判斷相等也是用=號。如果賦值的時候加上$號,會產生混淆。

還有一點要注意的就是單引號(')字串 中的變數不會被替換。

 

Js代碼
  1. var=World   
  2. var2='$var World'  
  3. echo $var2  
var=Worldvar2='$var World'echo $var2

上面的語句輸出結果:$var World

這個可以用來輸出$等特殊符號,而不用擔心字元被當作變數替換。

二.語句

1.shell的語句不必用;號結束,除非是同一行寫幾個語句的時候。

2.shell中的語句塊不用{}號擴起來。if語句一般就用fi表示結束。當然這個也有特例,後面會提到。

3.if語句

Js代碼
  1. if [ condition ]   
  2. then    
  3.     action   
  4. elif [ condition2 ]   
  5. then    
  6.     action2   
  7. .   
  8. .   
  9. .   
  10. elif [ condition3 ]   
  11. then    
  12. else  
  13.     actionx   
  14. fi  
if [ condition ]then     actionelif [ condition2 ]then     action2...elif [ condition3 ]then else    actionxfi

需要注意的是shell中沒有elseif,而是elif(這個縮寫也太變態了吧,有必要嗎?).

每個或者elif後跟著then,並且要換行或者用;分開。then可以和後面的action在一行。

 

3.for迴圈

Js代碼
  1. var="one two three four"  
  2. for x in $var  
  3. do  
  4.      echo $x   
  5. done  
var="one two three four"for x in $vardo     echo $xdone

 for迴圈用do  和 done表示開始結束,不要舉一反三,認為是用 rof結束。

4.while和util迴圈

 

Js代碼
  1. while [ condition ]   
  2.  do  
  3.      statements   
  4.  done  
while [ condition ] do     statements done

 

Js代碼
  1. until [ condition ]   
  2.  do  
  3.      statements   
  4.  done  
until [ condition ] do     statements done

 

 

 

5.條件陳述式

shell中的條件陳述式用[]號括起來,用於if,while,until等結構。

 條件判斷用=號,而不是==號。條件陳述式與[] 號之間要有空格分開。

如:

 

Js代碼
  1. gender="boy"  
  2. if [ "$gender" = "girl" ]   
  3. then   
  4.       echo 'Welcome!'  
  5. else  
  6.       echo 'We only welcome girl.'  
  7. fi  
gender="boy"if [ "$gender" = "girl" ]then      echo 'Welcome!'else      echo 'We only welcome girl.'fi

還有要注意的是條件陳述式中=號兩旁要有空格分開,否則shell會將條件陳述式整個作為一個字串處理,條件永遠為真。條件陳述式中的變數最好用"號引起來,否則如果該變數中有空格,shell就會報too many arguments錯誤。如果變數正好為空白,則會報 =: unary operator expected.錯誤。因為變數為空白的話,條件陳述式少了一邊,當然會出錯。所以,將字串變數用雙引號括起來是shell編程的好習慣,尤其在條件陳述式中。

 

其他的比較符號,如 >,<,不能直接在條件陳述式中使用,因為>號在shell中有特殊含義。下面是shell的比較子號表示方法:

 

Xml代碼
  1. 算術比較子   
  2.   
  3. num1-eq num2    等於  [ 3 -eq $mynum ]   
  4. num1-ne num2    不等於 [ 3 -ne $mynum ]   
  5. num1-lt num2    小於  [ 3 -lt $mynum ]   
  6. num1-le num2    小於或等於   [ 3 -le $mynum ]   
  7. num1-gt num2    大於  [ 3 -gt $mynum ]   
  8. num1-ge num2    大於或等於   [ 3 -ge $mynum ]  
算術比較子num1-eq num2 等於[ 3 -eq $mynum ]num1-ne num2 不等於[ 3 -ne $mynum ]num1-lt num2 小於[ 3 -lt $mynum ]num1-le num2 小於或等於[ 3 -le $mynum ]num1-gt num2 大於[ 3 -gt $mynum ]num1-ge num2 大於或等於[ 3 -ge $mynum ]

 

Xml代碼
  1. 字串比較運算子    
  2.   
  3. -z string   如果 string長度為零,則為真   [ -z "$myvar" ]   
  4. -n string   如果 string長度非零,則為真   [ -n "$myvar" ]   
  5. string1= string2    如果 string1與 string2相同,則為真   [ "$myvar" = "one two three" ]   
  6. string1!= string2   如果 string1與 string2不同,則為真   [ "$myvar" != "one two three" ]  
字串比較運算子 -z string 如果 string長度為零,則為真 [ -z "$myvar" ]-n string 如果 string長度非零,則為真 [ -n "$myvar" ]string1= string2 如果 string1與 string2相同,則為真 [ "$myvar" = "one two three" ]string1!= string2 如果 string1與 string2不同,則為真 [ "$myvar" != "one two three" ]

6.case 語句

 

Js代碼
  1. gender="boy"    
  2. case "$gender" in  
  3.       boy)   
  4.             echo "We only welcome girl."  
  5.             ;;   
  6.       girl)   
  7.             echo 'Welcome !'  
  8.             ;;   
  9.       *)   
  10.             echo "unknow."  
  11.             ;;   
  12.  esac    
gender="boy" case "$gender" in      boy)            echo "We only welcome girl."            ;;      girl)            echo 'Welcome !'            ;;      *)            echo "unknow."            ;; esac  

case語句的文法比較怪,乍一看比較彆扭。每個pattern用 半括弧括起來,用;;結束。

三.算術

shell 預設是用來處理字串的,所以如果你直接運行:

Js代碼
  1. echo 1+1  
echo 1+1

 它會直接輸出1+1,而不會輸出2。 如果需要計算運算式的值,則只需用"$((" 和 "))"將運算式括起。

Js代碼
  1. echo $((1+1))  
echo $((1+1))

 

四.函數

Js代碼
  1. add(){   
  2.     result=0   
  3.     for n in $*   
  4.     do  
  5.         result=$(($result+$n))   
  6.     done   
  7.     return $result   
  8. }  
add(){    result=0    for n in $*    do        result=$(($result+$n))    done    return $result}

 執行:

 

Java代碼
  1. add 1 2 3  
  2. echo $?   
  3. echo $result  
add 1 2 3echo $?echo $result

兩個輸出結果都是:6.

這裡需要幾點說明.shell中是不能直接獲得函數的傳回值的,如果你要用函數傳回值,只能用全域變數傳輸。shell中的變數預設都是全域的,除非你在前面加了local修飾符。如上面的例子,在函數外面,result變數也是可見的。如果你在result前加local修飾,result變數在函數外就不可見了。但shell會把函數傳回值放在$?全域變數中,你可以用$? 來取得前個函數調用的傳回值。$*可以獲得函數的所有輸入參數,$1表示第一個參數,以此類推。

 

五.其他

shell內建的一些特徵,可以很容易的處理檔案,以及和其他程式互動。

Xml代碼
  1. 檔案比較子   
  2.   
  3. -e filename     如果 filename存在,則為真   [ -e /var/log/syslog ]   
  4. -d filename     如果 filename為目錄,則為真  [ -d /tmp/mydir ]   
  5. -f filename     如果 filename為常規檔案,則為真    [ -f /usr/bin/grep ]   
  6. -L filename     如果 filename為符號連結,則為真    [ -L /usr/bin/grep ]   
  7. -r filename     如果 filename可讀,則為真   [ -r /var/log/syslog ]   
  8. -w filename     如果 filename可寫,則為真   [ -w /var/mytmp.txt ]   
  9. -x filename     如果 filename可執行,則為真  [ -L /usr/bin/grep ]   
  10. filename1-nt filename2  如果 filename1比 filename2新,則為真    [ /tmp/install/etc/services -nt /etc/services ]   
  11. filename1-ot filename2  如果 filename1比 filename2舊,則為真    [ /boot/bzImage -ot arch/i386/boot/bzImage ]  
檔案比較子-e filename 如果 filename存在,則為真 [ -e /var/log/syslog ]-d filename 如果 filename為目錄,則為真 [ -d /tmp/mydir ]-f filename 如果 filename為常規檔案,則為真 [ -f /usr/bin/grep ]-L filename 如果 filename為符號連結,則為真 [ -L /usr/bin/grep ]-r filename 如果 filename可讀,則為真 [ -r /var/log/syslog ]-w filename 如果 filename可寫,則為真 [ -w /var/mytmp.txt ]-x filename 如果 filename可執行,則為真 [ -L /usr/bin/grep ]filename1-nt filename2 如果 filename1比 filename2新,則為真 [ /tmp/install/etc/services -nt /etc/services ]filename1-ot filename2 如果 filename1比 filename2舊,則為真 [ /boot/bzImage -ot arch/i386/boot/bzImage ]

 

for 迴圈中很容易遍曆檔案

Js代碼
  1. for file in /home/*   
  2. do  
  3.    if [ -d "$file" ]    
  4.    then   
  5.       echo $file is a directory   
  6.     fi   
  7. done  
for file in /home/*do   if [ -d "$file" ]    then      echo $file is a directory    fidone

很容易調用其他程式的輸出結果:

 

Js代碼
  1. for user in `awk -F":" '{ print $1 }' /etc/passwd`   
  2. do  
  3.     echo find user $user   
  4. done  
for user in `awk -F":" '{ print $1 }' /etc/passwd`do    echo find user $userdone

 shell腳步中要使用其他命令的輸出結果,只需用`符號把命令包含起來。注意:這個符號不是單引號,在鍵盤左上方那個位置。

 

六. 後記

基本的shell文法就學了這些,進階的還沒弄通。這篇筆記也差不多長了,別的再邊學邊寫。shell是基礎,要配合awk,grep,sed這些工具才能發揮出效果。最近在看《unix編程藝術》,上面談到了*nix系統的幾個哲學基礎原則,其中有個原則就是:

組合原則:設計時考慮拼接組合

*nix系統程式的的輸入和輸出一般都是簡單,文本化,面向流的格式。這樣便於程式和程式之間的互動和拼接。*nix系統下的程式一般都只完成單一功能,如果你需要要一個複雜的功能,那就需要把小程式拼接在一起。這一特徵也決定了shell在*uix系統中的重要性。

 

七.shell學習資料

1.IBM Shell編程系列 

本文中的許多例子以及資料就是來自該系列教程

2.Bash 參考手冊

Gnu的bash官方參考手冊

 

相關文章

聯繫我們

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