<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                隨著程序變得更加龐大和復雜,設計,編碼和維護它們也變得更加困難。對于任意一個大項目而言, 把繁重,復雜的任務分割為細小且簡單的任務,往往是一個好主意。想象一下,我們試圖描述 一個平凡無奇的工作,一位火星人要去市場買食物。我們可能通過下面一系列步驟來形容整個過程: * 上車 * 開車到市場 * 停車 * 買食物 * 回到車中 * 開車回家 * 回到家中 然而,火星人可能需要更詳細的信息。我們可以進一步細化子任務“停車”為這些步驟: * 找到停車位 * 開車到停車位 * 關閉引擎 * 拉緊手剎 * 下車 * 鎖車 這個“關閉引擎”子任務可以進一步細化為這些步驟,包括“關閉點火裝置”,“移開點火匙”等等,直到 已經完整定義了要去市場買食物整個過程的每一個步驟。 這種先確定上層步驟,然后再逐步細化這些步驟的過程被稱為自頂向下設計。這種技巧允許我們 把龐大而復雜的任務分割為許多小而簡單的任務。自頂向下設計是一種常見的程序設計方法, 尤其適合 shell 編程。 在這一章中,我們將使用自頂向下的設計方法來進一步開發我們的報告產生器腳本。 ## Shell 函數 目前我們的腳本執行以下步驟來產生這個 HTML 文檔: * 打開網頁 * 打開網頁標頭 * 設置網頁標題 * 關閉網頁標頭 * 打開網頁主體部分 * 輸出網頁標頭 * 輸出時間戳 * 關閉網頁主體 * 關閉網頁 為了下一階段的開發,我們將在步驟7和8之間添加一些額外的任務。這些將包括: * 系統正常運行時間和負載。這是自上次關機或重啟之后系統的運行時間,以及在幾個時間間隔內當前運行在處理 中的平均任務量。 * 磁盤空間。系統中存儲設備的總使用量。 * 家目錄空間。每個用戶所使用的存儲空間數量。 如果對于每一個任務,我們都有相應的命令,那么通過命令替換,我們就能很容易地把它們添加到我們的腳本中: ~~~ #!/bin/bash # Program to output a system information page TITLE="System Information Report For $HOSTNAME" CURRENT_TIME=$(date +"%x %r %Z") TIME_STAMP="Generated $CURRENT_TIME, by $USER" cat << _EOF_ <HTML> <HEAD> <TITLE>$TITLE</TITLE> </HEAD> <BODY> <H1>$TITLE</H1> <P>$TIME_STAMP</P> $(report_uptime) $(report_disk_space) $(report_home_space) </BODY> </HTML> _EOF_ ~~~ 我們能夠用兩種方法來創建這些額外的命令。我們可以分別編寫三個腳本,并把它們放置到 環境變量 PATH 所列出的目錄下,或者我們也可以把這些腳本作為 shell 函數嵌入到我們的程序中。 我們之前已經提到過,shell 函數是位于其它腳本中的“微腳本”,作為自主程序。Shell 函數有兩種語法形式: ~~~ function name { commands return } and name () { commands return } ~~~ 這里的 name 是函數名,commands 是一系列包含在函數中的命令。 兩種形式是等價的,可以交替使用。下面我們將查看一個說明 shell 函數使用方法的腳本: ~~~ 1 #!/bin/bash 2 3 # Shell function demo 4 5 function funct { 6 echo "Step 2" 7 return 8 } 9 10 # Main program starts here 11 12 echo "Step 1" 13 funct 14 echo "Step 3" ~~~ 隨著 shell 讀取這個腳本,它會跳過第1行到第11行的代碼,因為這些文本行由注釋和函數定義組成。 從第12行代碼開始執行,有一個 echo 命令。第13行會調用 shell 函數 funct,然后 shell 會執行這個函數, 就如執行其它命令一樣。這樣程序控制權會轉移到第六行,執行第二個 echo 命令。然后再執行第7行。 這個 return 命令終止這個函數,并把控制權交給函數調用之后的代碼(第14行),從而執行最后一個 echo 命令。注意為了使函數調用被識別出是 shell 函數,而不是被解釋為外部程序的名字,所以在腳本中 shell 函數定義必須出現在函數調用之前。 我們將給腳本添加最小的 shell 函數定義: ~~~ #!/bin/bash # Program to output a system information page TITLE="System Information Report For $HOSTNAME" CURRENT_TIME=$(date +"%x %r %Z") TIME_STAMP="Generated $CURRENT_TIME, by $USER" report_uptime () { return } report_disk_space () { return } report_home_space () { return } cat << _EOF_ <HTML> <HEAD> <TITLE>$TITLE</TITLE> </HEAD> <BODY> <H1>$TITLE</H1> <P>$TIME_STAMP</P> $(report_uptime) $(report_disk_space) $(report_home_space) </BODY> </HTML> _EOF_ ~~~ Shell 函數的命名規則和變量一樣。一個函數必須至少包含一條命令。這條 return 命令(是可選的)滿足要求。 ## 局部變量 目前我們所寫的腳本中,所有的變量(包括常量)都是全局變量。全局變量在整個程序中保持存在。 對于許多事情來說,這很好,但是有時候它會使 shell 函數的使用變得復雜。在 shell 函數中,經常期望 會有局部變量。局部變量只能在定義它們的 shell 函數中使用,并且一旦 shell 函數執行完畢,它們就不存在了。 擁有局部變量允許程序員使用的局部變量名,可以與已存在的變量名相同,這些變量可以是全局變量, 或者是其它 shell 函數中的局部變量,卻不必擔心潛在的名字沖突。 這里有一個實例腳本,其說明了怎樣來定義和使用局部變量: ~~~ #!/bin/bash # local-vars: script to demonstrate local variables foo=0 # global variable foo funct_1 () { local foo # variable foo local to funct_1 foo=1 echo "funct_1: foo = $foo" } funct_2 () { local foo # variable foo local to funct_2 foo=2 echo "funct_2: foo = $foo" } echo "global: foo = $foo" funct_1 echo "global: foo = $foo" funct_2 echo "global: foo = $foo" ~~~ 正如我們所看到的,通過在變量名之前加上單詞 local,來定義局部變量。這就創建了一個只對其所在的 shell 函數起作用的變量。在這個 shell 函數之外,這個變量不再存在。當我們運行這個腳本的時候, 我們會看到這樣的結果: ~~~ [me@linuxbox ~]$ local-vars global: foo = 0 funct_1: foo = 1 global: foo = 0 funct_2: foo = 2 global: foo = 0 ~~~ 我們看到對兩個 shell 函數中的局部變量 foo 賦值,不會影響到在函數之外定義的變量 foo 的值。 這個功能就允許 shell 函數能保持各自以及與它們所在腳本之間的獨立性。這個非常有價值,因為它幫忙 阻止了程序各部分之間的相互干涉。這樣 shell 函數也可以移植。也就是說,按照需求, shell 函數可以在腳本之間進行剪切和粘貼。 ## 保持腳本運行 當開發程序的時候,保持程序的可執行狀態非常有用。這樣做,并且經常測試,我們就可以在程序 開發過程的早期檢測到錯誤。這將使調試問題容易多了。例如,如果我們運行這個程序,做一個小的修改, 然后再次執行這個程序,最后發現一個問題,非常有可能這個最新的修改就是問題的來源。通過添加空函數, 程序員稱之為占位符,我們可以在早期階段證明程序的邏輯流程。當構建一個占位符的時候, 能夠包含一些為程序員提供反饋信息的代碼是一個不錯的主意,這些信息展示了正在執行的邏輯流程。 現在看一下我們腳本的輸出結果: ~~~ [me@linuxbox ~]$ sys_info_page <HTML> <HEAD> <TITLE>System Information Report For twin2</TITLE> </HEAD> <BODY> <H1>System Information Report For linuxbox</H1> <P>Generated 03/19/2009 04:02:10 PM EDT, by me</P> </BODY> </HTML> ~~~ 我們看到時間戳之后的輸出結果中有一些空行,但是我們不能確定這些空行產生的原因。如果我們 修改這些函數,讓它們包含一些反饋信息: ~~~ report_uptime () { echo "Function report_uptime executed." return } report_disk_space () { echo "Function report_disk_space executed." return } report_home_space () { echo "Function report_home_space executed." return } ~~~ 然后再次運行這個腳本: ~~~ [me@linuxbox ~]$ sys_info_page <HTML> <HEAD> <TITLE>System Information Report For linuxbox</TITLE> </HEAD> <BODY> <H1>System Information Report For linuxbox</H1> <P>Generated 03/20/2009 05:17:26 AM EDT, by me</P> Function report_uptime executed. Function report_disk_space executed. Function report_home_space executed. </BODY> </HTML> ~~~ 現在我們看到,事實上,執行了三個函數。 我們的函數框架已經各就各位并且能工作,是時候更新一些函數代碼了。首先,是 report_uptime 函數: ~~~ report_uptime () { cat <<- _EOF_ <H2>System Uptime</H2> <PRE>$(uptime)</PRE> _EOF_ return } ~~~ 這些代碼相當直截了當。我們使用一個 here 文檔來輸出標題和 uptime 命令的輸出結果,命令結果被 標簽包圍, 為的是保持命令的輸出格式。這個 report_disk_space 函數類似: ~~~ report_disk_space () { cat <<- _EOF_ <H2>Disk Space Utilization</H2> <PRE>$(df -h)</PRE> _EOF_ return } ~~~ 這個函數使用 df -h 命令來確定磁盤空間的數量。最后,我們將建造 report_home_space 函數: ~~~ report_home_space () { cat <<- _EOF_ <H2>Home Space Utilization</H2> <PRE>$(du -sh /home/*)</PRE> _EOF_ return } ~~~ 我們使用帶有 -sh 選項的 du 命令來完成這個任務。然而,這并不是此問題的完整解決方案。雖然它會 在一些系統(例如 Ubuntu)中起作用,但是在其它系統中它不工作。這是因為許多系統會設置家目錄的 權限,以此阻止其它用戶讀取它們,這是一個合理的安全措施。在這些系統中,這個 report_home_space 函數, 只有用超級用戶權限執行我們的腳本時,才會工作。一個更好的解決方案是讓腳本能根據用戶的使用權限來 調整自己的行為。我們將在下一章中討論這個問題。 > 你的 .bashrc 文件中的 shell 函數 > > Shell 函數是更為完美的別名替代物,實際上是創建較小的個人所用命令的首選方法。別名 非常局限于命令的種類和它們支持的 shell 功能,然而 shell 函數允許任何可以編寫腳本的東西。 例如,如果我們喜歡 為我們的腳本開發的這個 report_disk_space shell 函數,我們可以為我們的 .bashrc 文件 創建一個相似的名為 ds 的函數: > > ~~~ > ds () { > echo “Disk Space Utilization For $HOSTNAME” > df -h > } > > ~~~ ## 總結歸納 這一章中,我們介紹了一種常見的程序設計方法,叫做自頂向下設計,并且我們知道了怎樣 使用 shell 函數按照要求來完成逐步細化的任務。我們也知道了怎樣使用局部變量使 shell 函數 獨立于其它函數,以及其所在程序的其它部分。這就有可能使 shell 函數以可移植的方式編寫, 并且能夠重復使用,通過把它們放置到多個程序中;節省了大量的時間。 ## 拓展閱讀 * Wikipedia 上面有許多關于軟件設計原理的文章。這里是一些好文章: [http://en.wikipedia.org/wiki/Top-down_design](http://en.wikipedia.org/wiki/Top-down_design) [http://en.wikipedia.org/wiki/Subroutines](http://en.wikipedia.org/wiki/Subroutines)
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看