<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      快速學習Bash

      作者:Vamei 出處:http://www.rzrgm.cn/vamei 嚴禁轉載。


      Shell是Linux下經典的文本互動方式,而Bash是現在最常用的一種Shell。我在這里總結了Bash的要點知識。

       

      Shell綜述

      Linux圖形化桌面算不上精美。幸好,Linux提供了更好的與樹莓派互動的方式:Shell。打開終端(Terminal),桌面上就會出現一個黑色背景的窗口,里面就運行著一個Shell。如果你敲擊鍵盤,會發現字符會顯示在$提示符的后面,形成一串文本形式的命令。所謂的Shell,就是運行在終端中的文本互動程序。Shell分析你的文本輸入,然后把文本轉換成相應的計算機動作。

       

      在后面的內容中,我將用$來表示Linux系統Shell的命令提示符。比如說輸入date命令:

      $date

      date用于日期時間的相關功能。敲擊回車鍵Enter后,Shell會顯示出系統當前的時間。

       

      Shell看起來簡陋,但實際上比圖形化桌面強大得多。它是Unix體系下的文本交互界面。你只需要用鍵盤來輸入文本,就可以和操作系統交互。但這還是不夠具體。說到底,Shell其實是一個運行著的程序。這個程序接收到你按下回車鍵之間的輸入,就會對輸入的文本進行分析。比如下面這個命令:

      $free -h

      包括空格在內總共7個字符。Shell程序會通過空格,區分出命令的不同部分。第一個部分是命令名。剩下的部分是選項和參數。在這個例子中,Shell會進一步分析第二個部分,發現這一部分的開頭是"-"字符,從而知道它是一個選項。

       

      有了命令名,Shell下一步就要執行該命令名對應的動作。這聽起來就像是在戲劇舞臺上,演員按照腳本演戲。Shell命令可以分為如下三類:

      • Shell內建函數(built-in function)
      • 可執行文件(executable file)
      • 別名(alias)

      Shell的內建函數是Shell自帶的功能,而可執行文件是保存在Shell之外的腳本,提供了額外的功能。Shell必須在系統中找到對應命令名的可執行文件,才能正確執行。我們可以用絕對路徑來告訴Shell可執行文件所在的位置。如果用戶只是給出了命令名,而沒有給出準確的位置,那么Shell必須自行搜索一些特殊的位置,也就是所謂的默認路徑。Shell會執行第一個名字和命令名相同的可執行文件。這就相當于,Shell幫我們自動補齊了可執行文件的位置信息。我們可以通過which命令,來確定命令名對應的是哪個可執行文件:

      $which date

       

      別名是給某個命令一個簡稱,以后在Shell中就可以通過這個簡稱來調用對應的命令。在Shell中,我們可以用alias來定義別名:

      $alias freak="free -h"

      Shell會記住我們的別名定義。以后我在這個Shell中輸入命令freak時,都將等價于輸入free -h。

       

      在Shell中,我們可以通過type命令來了解命令的類型。如果一個命令是可執行文件,那么type將打印出文件的路徑。

      $type date
      $type pwd

      總的來說,Shell就是根據空格和其他特殊符號,來讓電腦理解并執行用戶要求的動作。到了后面,我們還將看到Shell中其他的特殊符號。

       

      Shell的選擇

      Shell是文本解釋器程序的統稱,所以包括了不止一種Shell。常見的Shell有sh、bash、ksh、rsh、csh等。在樹莓派中,就安裝了sh和bash兩個Shell解釋器。sh的全名是Bourne Shell。名字中的玻恩就是這個Shell的作者。而bash的全名是Bourne Again Shell。最開始在Unix系統中流行的是sh,而bash作為sh的改進版本,提供了更加豐富的功能。一般來說,都推薦使用bash作為默認的Shell。樹莓派,以及其他Linux系統中廣泛安裝sh,都是出于兼容歷史程序的目的。

       

      我們可以通過下面的命令來查看當前的Shell類型:

      $echo $SHELL

      echo用于在終端打印出文本。而$是一個新的Shell特殊符號。它提示Shell,后面跟隨的不是一般的文本,而是用于存儲數據的變量。Shell會根據變量名找到真正的文本,替換到變量所在的位置。SHELL變量存儲了當前使用的Shell的信息你可以在bash中用sh命令啟動sh,并可以用exit命令從中退出。

       

      命令的選項和參數

      我們已經看到,一行命令里還可以包含著選項和參數。總的來說,選項用于控制命令的行為,而參數說明了命令的作用對象。比如說:

      $uname -m

       

      在上面的命令中,選項-m影響了命令uname的行為,導致uname輸出了樹莓派的CPU型號。如果不是該選項的影響,uname輸出的將是"Linux"。我們不妨把每個命令看做多功能的瑞士軍刀,而選項讓命令在不同的功能間切換。由一個"-"引領一個英文字母,這成為短選項。多個短選項的字母可以合在一起,跟在同一個"-"后面。比如,下面的兩個命令就等價:

      $uname -m -r
      $uname -mr

       

      此外還有一種長選項,是用"--"引領一整個英文單詞,比如:

      $date --version

      上面的命令將輸出date程序的版本信息。

       

      如果說選項控制了瑞士軍刀的行為,那么參數就提供了瑞士軍刀發揮用場的原材料。就拿echo這個命令來說,它能把字符打印到終端。它選擇打印的對象,正是它的參數:

      $echo hello

       

      有的時候,選項也會攜帶變量,以便來說明選項行為的原材料。比如:

      $sudo date --set="1999-01-01 08:00:00"

      選項"--set"用于設置時間,用等號連接的,就是它的參數。date會把日期設置成這一變量所代表的日期。如果用短選項,那么就要用空格取代等號了:

      $sudo date -s "1999-01-01 08:00:00"

      值得注意的是,Shell對空格敏感。當一整個參數信息中包含了空格時,我們需要用引號把參數包裹起來,以便Shell能識別出這是一個整體。

       

      所謂的選項和參數提供給命令的附加信息。因此,命令最終會拿這些字符串做什么,是由命令自己決定的。因此,有時會發現一些特異的選項或參數用法。這個時候,你就要從文檔中尋找答案。

       

      變量

      我們可以在Bash中輸入一行的命令。Bash會把輸入的命令轉化為特定的動作。從這一節起,我們將看到Bash的可編程性。Bash提供了某些類似于C語言那樣的編程語法,從而允許你用編程的方式,來組合使用Linux系統。我們首先看Bash用變量存儲數據的能力。正如我們在C語言中看到的,變量是內存中的一塊兒空間,可以用于存儲數據。我們可以通過變量名來引用變量中保持的數據。借助變量,程序員可以復用出現過的數據。Bash中也有變量,但Bash的變量只能存儲文本。

       

      1)變量賦值

      Bash和C類似,同樣用“=”來表示賦值。比如:

      $var=World

      就是把文本World存入名為var的變量,即賦值。根據Bash的語法,賦值符號“=”的前后不留空格。賦值號右邊的文本內容會存入賦值號左邊的變量。

       

      如果文本中包含空格,那么你可以用單引號或雙引號來包裹文本。比如:

      $var='abc bcd'

      或者:

      $var="abc bcd"

       

      在Bash中,我們可以把一個命令輸出的文本直接賦予給一個變量:

      $now=`date`

      借助``符號,date命令的輸出存入了變量now。

       

      我們還可以把一個變量中的數據賦值給另一個變量:

      $another=$var

        

      2)引用變量

      我們可以用$var的方式來引用變量。在Bash中,所謂的引用變量就是把變量翻譯成變量中存儲的文本。比如:

      $var=World
      $echo $var

       就會打印出World,即變量中保存的文本。

       

      在Bash中,你還可以在一段文本中嵌入變量。Bash也會把變量替換成變量中保存的文本。比如: 

      $echo Hello$var

       文本將打印出HelloWorld。

       

      為了避免變量名和尾隨的普通文本混淆,我們也可以換用${}的方式來標識變量。比如說:

      $echo $varIsGood

       由于Bash中并沒有varIsGood這個變量,所以Bash將打印空白行。但如果將命令改為: 

      $echo ${var}IsGood

       Bash通過${}識別出變量var,并把它替換成數據。最終echo命令打印出WorldIsGood。

       

      在Bash中,為了把一段包含空格的文本當做單一參數,就需要用到單引號或雙引號。你可以在雙引號中使用變量。比如:

      $echo "Hello $var"

       將打印Hello World。與此相對,Bash會忽視單引號中的變量引用,所以單引號中的變量名只會被當做普通文本,比如:

      $echo 'Hello $var'

       將打印Hello $var。

       

      數學運算

      在Bash中,數字和運算符都被當做普通文本。所以你無法像C語言一樣便捷地進行數學運算。比如執行下面的命令:

      $result=1+2
      $echo $result

      Bash并不會進行任何運算。它只會打印文本“1+2”。

       

      在Bash中,你還可以通過$(())語法來進行數值運算。在雙括號中你可以放入整數的加減乘除表達式。Bash會對其中的內容進行數值運算。比如

      $echo $((2 + (5*2)))

       將打印運算結果12。此外,在$(())中,你也可以使用變量。比如: 

      $var=1
      $echo $(($var + (5*2)))

       將打印運算結果11。

       

      你可以用Bash實現多種整數運算:

      ? 加法:$(( 1 + 6 ))。結果為7。
      ? 減法:$(( 5 – 3 ))。結果為2。
      ? 乘法:$(( 2*2 ))。結果為4。
      ? 除法:$(( 9/3 ))。結果為3。
      ? 求余:$(( 5%3 ))。結果為2。
      ? 乘方:$(( 2**3 ))。結果為8。

       

      現在,你就可以把數學運算結果存入變量:

      $result=$(( 1 + 2 ))

       

       

      返回代碼

      在Linux中,每個可執行程序會有一個整數的返回代碼。按照Linux慣例,當程序正常運行完畢并返回時,將返回整數0。因此,C程序中返回0的語句,都出現在C程序中main函數的最后一句。例如下面的foo.c程序:

      int main(void) {
        int a;
        int b;
        int c;
      
        a = 6;
        b = 2;
        c = 6/2;
      
        return 0;
      }

       這段程序可以正常運行。因此,它將在最后一句執行return語句,程序的返回代碼是0。在Shell中,我們運行了程序后,可以通過$?變量來獲知返回碼。比如:

      $gcc foo.c
      $./a.out
      $echo $?

       

      如果一個程序運行異常,那么這個程序將返回非0的返回代碼。比如刪除一個不存在的文件: 

      $rm none_exist.file
      $echo $?

       

       在Linux中,可以在一個行命令中執行多個程序。比如:

      $touch demo.file; ls;

       

      在執行多個程序時,我們可以讓后一個程序的運行參考前一個程序的返回代碼。比如說,只有前一個程序返回成功代碼0,才讓后一個程序運行: 

      $rm demo.file && echo "rm succeed"

      如果rm命令順利運行,那么第二個echo命令將執行。

       

      還有一種情況,是等到前一個程序失敗了,才運行后一個程序,比如:

      $rm demo.file || echo "rm fail"

      如果rm命令失敗,第二個echo命令才會執行。

       

      Bash腳本

      你還可以把多行的Bash命令寫入一個文件,成為所謂的Bash腳本。當Bash腳本執行時,Shell將逐行執行腳本中的命令。編寫Bash腳本,是我們開始實現Bash代碼復用的第一步。

       

      1)腳本的例子

      用文本編輯器編寫一個Bash腳本hello_world.bash: 

      #!/bin/bash
      
      echo Hello
      echo World

       

      腳本的第一行說明了該腳本使用的Shell,即/bin/bash路徑的Bash程序。腳本正文是兩行echo命令。運行腳本的方式和運行可執行程序的方式類似,都是: 

      $./hello_world.bash

      需要注意的是,如果用戶不具有執行Bash腳本文件的權限,那么他將無法執行Bash腳本。此時,用戶必須更換文件權限,或者以其他身份登錄,才能執行腳本。當腳本運行時,兩行命令將按照由上至下的順序依次執行。Shell將打印兩行文本:

      Hello

      World

       

      Bash腳本是一種復用代碼的方式。我們可以用Bash腳本實現特定的功能。由于該功能記錄在腳本中,因此我可以反復地運行同一個文件來實現相同的功能,而不是每次想用的時候都要重新敲一遍命令。我們看一個簡單的Bash腳本hw_info.bash,它將計算機的信息存入到名為log的文件中:

      #!/bin/bash
      
      echo "Information of Vamei's computer:" > log
      lscpu >> log
      uname –a >> log
      free –h >> log

        

      2)腳本參數

      和可執行程序類似,Bash腳本運行時,也可以攜帶參數。這些參數可以在Bash腳本中以變量的形式使用。比如test_arg.bash:

      #!/bin/bash
      
      echo $0
      echo $1
      echo $2

       

      在Bash中,你可以用$0、$1、$2……的方式,來獲得Bash腳本運行時的參數。我們用下面的方式運行Bash腳本:

      $./test_arg.bash hello world

      $0是命令的第一部分,也就是./test_arg.bash。$1代表了參數hello,而$2代表了參數world。因此,上面程序將打印:

      ./test_arg.bash

      hello

      world

       

      如果變更參數,同一段腳本將有不同的行為。這大大提高了Bash腳本的靈活性。上面的hw_info.bash腳本中,我們把輸出文件名寫死成log。我們也可以修改腳本,用參數作為輸出文件的文件名:

      #!/bin/bash
      
      echo "Information of Vamei's computer:" > $1
      lscpu >> $1
      uname –a >> $1
      free –h >> $1

       

      借助參數,我們就可以自由地設置輸出文件的名字:

      $./hw_info.bash output.file

       

      3)腳本的返回代碼

      和可執行程序類似,腳本也可以有返回代碼。還是按照慣例,腳本正常退出時返回代碼0。在腳本的末尾,我們可以用exit命令來設置腳本的返回代碼。我們修改hello_world.bash:

      #!/bin/bash
      
      echo Hello
      echo World
      exit 0

      其實在腳本的末尾加一句exit 0并不必要。一個腳本如果正常運行完最后一句,會自動的返回代碼0。在腳本運行后,我們可以通過$?變量查詢腳本的返回代碼: 

      $./hello_world.bash
      $echo $?

       

      如果在腳本中部出現exit命令,腳本會直接在這一行停止,并返回該exit命令給出的返回代碼。比如下面的demo_exit.bash:

      #!/bin/bash
      
      echo hello
      exit 1
      echo world

      你可以運行該腳本,檢查其輸出結果,并查看其返回代碼。

       

      函數

      在Bash中,腳本和函數有很多相似的地方。腳本實現了一整個腳本文件的程序復用,而函數復用了腳本內部的部分程序。一個函數可以像腳本一個包含多個指令,用于說明該函數如果被調用會執行哪些活動。在定義函數時,我們需要花括號來標識函數包括的部分: 

      #!/bin/bash
      
      function my_info (){
      lscpu >> log
      uname –a >> log
      free –h >> log
      }
      
      my_info

        

      腳本一開始定義了函數my_info,my_info是函數名。關鍵字function和花括號都提示了該部分是函數定義。因此,function關鍵字并不是必須的。上面的腳本等效于:

      #!/bin/bash
      
      my_info (){
      lscpu >> log
      uname –a >> log
      free –h >> log
      }
      
      my_info

      花括號中的三行命令,就說明了函數執行時需要執行的命令。需要強調的是,函數定義只是食譜,并沒有轉化成具體的動作。腳本的最后一行是在調用函數。只有通過函數調用,函數內包含的命令才能真正執行。調用函數時,只需要一個函數名就可以了。

       

      像腳本一樣,函數調用時還可以攜帶參數。在函數內部,我們同樣可以用$1、$2這種形式的變量來使用參數:

      #!/bin/bash
      
      function my_info (){
      lscpu >> $1
      uname –a >> $1
      free –h >> $1
      }
      
      my_info output.file
      my_info another_output.file

      在上面的腳本中,進行了兩次函數調用。函數調用時,分別攜帶了參數output.file和another_output.file。

       

      跨腳本調用

      在Bash中使用source命令,可以實現函數的跨腳本調用。命令source的作用是在同一個進程中執行另一個文件中的Bash腳本。比如說,有兩個腳本,my_info.bash和app.bash。腳本my_info.sh中的內容是: 

      #!/bin/bash
      
      function my_info (){
      lscpu >> $1
      uname –a >> $1
      free –h >> $1
      }

       

      腳本app.bash中的內容是: 

      #!/bin/bash
      
      source my_info.bash
      my_info output.file

      運行app.bash時,執行到source命令那一行時,就會執行my_info.bash腳本。在app.bash的后續部分,就可以使用my_info.bash中的my_info函數。

       

       

      邏輯判斷

      我們已經介紹了函數和腳本兩種組合命令的方式。這兩種方式都可以把多行命令合并起來,組成一個功能單元。函數和腳本都實現了一定程度的代碼復用。從這一節起,我們將看到選擇和循環兩種語法結構,這兩種語法結構可以改變腳本的運行順序,從而編寫出更加靈活的程序。Bash除了可以進行數值運算,還可以進行邏輯判斷。邏輯判斷是決定某個說法的真假。我們在生活中很自然地進行各種各樣的邏輯判斷。比如“3大于2”這個說法,我們會說它是真的。邏輯判斷就是對一個說法判斷真假。在Bash中,我們可以用test命令來進行邏輯判斷:

      $test 3 -gt 2; echo $?

      命令test后面跟有一個判斷表達式,其中的-gt表示大于,即greater than。由于“3大于2”這一表達式為真,所以命令的返回代碼將是0。如果表達式為1,那么命令的返回代碼是1:

      $test 3 -lt 2; echo $?

      表達式中的-lt表示小于,即less than。

       

      數值大小和相等關系的判斷,是最常見的邏輯判斷。除了上面的大于和小于判斷,我們還可以進行以下的數值判斷:

      • 等于: $test 3 -eq 3; echo $? 
      • 不等于: $test 3 -ne 1; echo $? 
      • 大于等于: $test 5 -ge 2; echo $? 
      • 小于等于: $test 3 -le 1; echo $? 

       

      Bash中最常見的數據形式是文本,因此也提供了很多關于文本的判斷:

      • 文本相同: $test abc = abx; echo $? 
      • 文本不同: $test abc != abx; echo $? 
      • 按照詞典順序,一個文本在另一個文本之前: $test apple > tea; echo $? 
      • 按照詞典順序,一個文本在另一個文本之后: $test apple < tea; echo $? 

       

      Bash還可以對文件的狀態進行邏輯判斷:

      • 檢查一個文件是否存在: $test –e a.out; echo $? 
      • 檢查一個文件是否存在,而且是普通文件: $test –f file.txt; echo $? 
      • 檢查一個文件是否存在,而且是目錄文件: $test –d myfiles; echo $? 
      • 檢查一個文件是否存在,而且是軟連接: $test –L a.out; echo $? 
      • 檢查一個文件是否可讀: $test –r file.txt; echo $? 
      • 檢查一個文件是否可寫: $test –w file.txt; echo $? 
      • 檢查一個文件是否可執行: $test –x file.txt; echo $? 

       

      在做邏輯判斷時,可以把多個邏輯判斷條件用“與、或、非”的關系組合起來,形成復合的邏輯判斷。 

      ! expression
      expression1 –a expression2
      expression1 –o expression2

       

       

      選擇結構

      邏輯判斷可以獲得計算機和進程的狀態。進一步,Bash可以根據邏輯判斷,讓程序有條件地運行,這也就是所謂的選擇結構。選擇結構是一種語法結構,可以讓程序根據條件決定執行哪一部分的指令。最早的程序都是按照指令順序依次執行。選擇結構打破了這一順序,給程序帶來更高的靈活性。最簡單的,我們可以根據條件來決定是否執行某一部分程序,比如下面的demo_if.bash腳本:

      #!/bin/bash
      
      var = `whoami`
      if [ $var = "root" ]
      then
        echo "You are root"
        echo "You are my God."
      fi

      這個腳本中使用了最簡單的if結構。關鍵字if后面跟著[],里面是一個邏輯表達式。這個邏輯表達式就是if結構的條件。如果條件成立,那么if將執行then到fi之間包含的語句,我們稱之為隸屬于then的代碼塊。如果條件不成立,那么then的代碼塊不執行。這個例子的條件是判斷用戶是否為root。因此,如果是非root用戶執行該腳本,那么Shell不會打印任何內容。

       

      我們還可以通過if...then...else...結構,讓Bash腳本從兩個代碼塊中選擇一個執行。該選擇結構同樣有一個條件。如果條件成立,那么將執行then附屬的代碼塊,否則執行else附屬的代碼塊。下面的demo_if_else.bash腳本是一個小例子:

      #!/bin/bash
      
      filename=$1
      if [ -e $filename ]
      then
        echo "$filename exists"
      else
        echo "$filename NOT exists"
      fi
      
      echo "The End"

       

      if后面的“-e $filename”作為判斷條件。如果條件成立,即文件存在,那么執行then部分的代碼塊。如果文件不存在,那么腳本將執行else語句中的echo命令。末尾的fi結束整個語法結構。腳本繼續以順序的方式執行剩余內容。運行腳本: 

      $./demo_if_else.bash a.out

      腳本會根據a.out是否存在,打印出不同的內容。

       

      我們看到,在使用if...then...else...結構時,我們可以實現兩部分代碼塊的選擇執行。而在then代碼塊和else代碼塊內部,我們可以繼續嵌套選擇結構,從而實現更多個代碼塊的選擇執行。比如腳本demo_nest.bash:

      #!/bin/bash
      
      var=`whoami`
      echo "You are $var"
      
      if [ $var = "root" ]
      then
        echo "You are my God."
      else
        if [ $var = "vamei" ]
        then
          echo "You are a happy user."
        else
          echo "You are the Others."
        fi
      fi

       

      在Bash下,我們還可以用case語法來實現多程序塊的選擇執行。比如下面的腳本demo_case.bash: 

      #!/bin/bash
      
      var=`whoami`
      echo "You are $var"
      
      case $var in
      root)
      echo "You are God."
      ;;
      vamei)
      echo "You are a happy user."
      ;;
      *)
      echo "You are the Others."
      ;;
      esac

      這個腳本和上面的demo_nest.bash功能完全相同。可以看到case結構與if結構的區別。關鍵字case后面不再是邏輯表達式,而是一個作為條件的文本。后面的代碼塊分為三個部分,都以文本標簽)的形式開始,以;;結束。在case結構運行時,會逐個檢查文本標簽。當條件文本和文本標簽可以對應上時,Bash就會執行隸屬于該文本標簽的代碼塊。如果是用戶vamei執行該Bash腳本,那么條件文本和vamei標簽對應上,腳本就會打印:

      You are a happy user.

       

      文本標簽除了是一串具體的文本,還可以包含文本通配符。結構case中常用的通配符包括:

       

      通配符 含義 文本標簽例子 通過的條件文本
      * 任意文本 *) Xyz, 123, …
      ? 任意一個字符 a?c) abc, axc, …
      [] 范圍內一個字符 [1-5][b-d]) 2b, 3d, …

      上面的程序中最后一個文本標簽是通配符*,即表示任意條件文本都可以觸發此段代碼塊的運行。當然,前提是前面的幾個文本標簽都沒有“截胡”。

       

      循環結構

      循環結構是編程語言中另一種常見的語法結構。循環結構的功能是重復執行某一段代碼,直到計算機的狀態符合某一條件。在while語法中,Bash會循環執行隸屬于while的代碼塊,直到邏輯表達式不成立。比如下面的demo_while.bash:

      #!/bin/bash
      
      now=`date +'%Y%m%d%H%M'`
      deadline=`date --date='1 hour' +'%Y%m%d%H%M'`
      
      while [ $now -lt $deadline ]
      do
        date
        echo "not yet"
        sleep 10
        now=`date +'%Y%m%d%H%M'`
      done
      
      echo "now, deadline reached"

      關鍵字do和done之間的代碼是隸屬于該循環結構的代碼塊。在while后面跟著條件,該條件決定了代碼塊是否重復執行下去。這個條件是用當前的時間與目標時間對比。如果當前時間小于目標時間,那么代碼塊就會重復執行下去。否則,Bash將跳出循環,繼續執行后面的語句。

       

      如果while的條件始終是真,那么循環會一直進行下去。下面的程序就是以無限循環的形式,不斷播報時間: 

      #!/bin/bash
      
      while true 
      do
        date
        sleep 1
      done

       

      語法while的終止條件是一個邏輯判斷。如果在循環過程中改變邏輯判斷的內容,那么我們很難在程序執行之前預判循環進行的次數。正如我們之前在demo_while.bash中看到的,我們在循環進行過程中改變著作為條件的邏輯表達式,不斷地更新參與邏輯判斷的當前時間。與while語法對應的是for循環。這種語法會在程序進行前確定好循環進行的次數,比如demo_for.bash: 

      #!/bin/bash
      
      for var in `ls log*`
      do
        rm $var
      done

       

      在這個例子中,命令ls log*將返回所有以log開頭的文件名。這些文件名之間由空格分隔。循環進行時,Bash會依次取出一個文件名,賦值給變量var,并執行do和done之間隸屬于for結構的程序塊。由于ls命令返回的內容在是確定的,因此for循環進行的次數也會在一開始確定下來。

       

      在for語法中,我們也可以使用自己構建一個由空格分隔的文本。由空格區分出來的每個子文本會在循環中賦值給變量。比如:

      #!/bin/bash
      
      for user in vamei anna yutian
      do
        echo $user
      done

       

      此外,for循環還可以和seq命令配合使用。命令seq用于生成一個等差的整數序列。命令后面可以跟3個參數,第一個參數表示整數序列的開始數字,第二個參數表示每次增加多少,最后一個參數表示序列的終點。因此,下面命令: 

      $seq 1 2 10

      將返回:

      1 3 5 7 9

      可以看到,seq返回的也是由空格分隔開的文本。因此,seq的返回結果也可用于for循環。

       

      結合for循環和seq命令,我們可以解一些有趣的數學問題。比如高斯求和,是要計算從1到100的所有整數的和。我們可以用Bash解決: 

      #!/bin/bash
      
      total=0
      
      for number in `seq 1 1 100`
      do
        total=$(( $total + $number ))
      done
      
      echo $total

       

       這個問題還可以用do while循環來求解:

      #!/bin/bash
      
      total=0
      number=1
      while :
      do
        if [ $number -gt 100 ]
        then
          break
        fi
      
        total=$(( $total + $number ))
        number=$(($number + 1))
      done
      
      echo $total

      這里break語句的作用是在滿足條件時跳出循環。

       

      如果想計算1到100所有不被3整數的和,則可以使用continue語句,跳過所有被3整數的數:

      #!/bin/bash
      total=0
      for number in `seq 1 1 100`
      do
        if (( $number % 3 == 0 )) 
        then
          continue
        fi
        total=$(( $total + $number ))
      done
      
      echo $total

       

      Bash與C語言

      到了這里,我們已經介紹完Bash語言的基本語法。Bash語言和C語言都是Linux下的常用語言。它們都能通過特定的語法來編寫程序,而程序運行后都能實現某些功能。盡管在語法細節上存在差異,但兩種語言都有以下語法:

      • 變量:在內存中儲存數據
      • 循環結構:重復執行代碼塊
      • 選擇結構:根據條件執行代碼塊
      • 函數:復用代碼塊

      編程語言的作者在設計語言時,往往會借鑒已有編程語言的優點。這是編程語言之間相似性的一大原因。程序員往往要掌握不止一套編程語言。相似的語法特征,會讓程序員在學習新語言時感到親切,從而促進語言的推廣。

      Bash和C的相似性,也來自于它們共同遵守的編程范式——面向過程編程。支持面向過程編程的語言,一般都會提供類似于函數的代碼封裝方式。函數把多行指令包裝成一個功能。只要知道了函數名,程序可以通過調用函數來使用函數功能,最終實現代碼復用。除了面向過程編程,還有面向對象和函數式的編程范式。每種編程范式都提供了特定的代碼封裝方式,并達到代碼復用的目的。值得注意的是,近年來出現的新語言往往會支持不止一種編程范式。

      除了相似性,我們還應該注意到Bash和C程序的區別。Bash的變量只能是文本類型,C的變量卻可以有整數、浮點數、字符等類型。Bash的很多功能,如加減乘除運算,都是調用其他程序實現的。而C直接就可以進行加減乘除運算。可以說,C語言是一門真正的編程語言。C程序最終會編譯成二進制的可執行文件。CPU可以直接理解這些文件中的指令。

      另一方面,Bash是一個Shell。它本質上是一個命令解釋器程序,而不是編程語言。用戶可以通過命令行的方式,來調用該程序的某些功能。所謂的Bash編程,只是命令解釋器程序提供的一種互動方法。Bash腳本只能和Bash進程互動。它不能像C語言一樣,直接調用CPU的功能。因此,Bash能實現的功能會受限,運行速度上也比不上可執行文件。

      但另一反面,Bash腳本也有它的好處。 C語言能接觸到很底層的東西,但使用起來也很復雜。有時候,即使你已經知道如何用C實現一個功能,寫代碼依然是一個很繁瑣的過程。Bash正相反。由于Bash可以便捷地調用已有的程序,因此很多工作可以用數行的腳本解決。此外,Bash腳本不需要編輯,就可以由Bash進程理解并執行。因此,開發Bash腳本比寫C程序要快很多。Linux的系統運維工作,如定期備份、文件系統管理等,就經常使用到Bash腳本。總之,Bash編程知識是晉級為資深Linux用戶的必要條件。

       

      歡迎閱讀“騎著企鵝采樹莓”系列文章

       

      posted @ 2017-12-30 22:55  Vamei  閱讀(14949)  評論(5)    收藏  舉報
      主站蜘蛛池模板: 日本国产一区二区三区在线观看| 亚洲第一二三区日韩国产| 吉川爱美一区二区三区视频| 亚洲成aⅴ人在线电影| 中文字幕日韩有码一区| 日本一区二区三区专线| 国产精品久久久久影院色| 日韩欧美视频一区二区三区| 久久久久蜜桃精品成人片公司 | 亚洲人成网站999久久久综合| 色一伊人区二区亚洲最大| 亚洲国产大胸一区二区三区| 久久久精品94久久精品| 福利视频一区二区在线| 东光县| 少妇爽到呻吟的视频| 精品熟女少妇免费久久| 成av人片一区二区久久| 亚洲人成网线在线播放VA| 日本免费一区二区三区日本| 亚洲成在人线AV品善网好看| 狠狠综合久久综合88亚洲| 亚洲精品国产第一区二区| 性欧美丰满熟妇xxxx性| 国内揄拍国内精品少妇国语 | 天天躁夜夜躁狠狠喷水| 国产成人无码A区在线观| 日本黄页网站免费观看| 国内精品久久久久影院网站| 男女爽爽无遮挡午夜视频| 亚洲国产成人久久综合人| 亚洲日韩一区二区| 国产免费网站看v片元遮挡| 久久不卡精品| 性色av一区二区三区精品| 好男人社区神马在线观看www | 亚洲国产精品综合久久2007| 永和县| 在线成人国产天堂精品av| 中文字幕日韩精品有码视频 | 国产在线精品福利91香蕉|