開放原始碼技術文件網 基本概念

最後修改日期為 JUN 8, 2021

前言

會願意學 shell 程式設計的程式人,通常也是老練的類 Unix 系統使用者。但我們在本文中仍會從基本開始,帶著讀者了解 shell 的基本概念。

取得類 Unix 系統

真正的 Unix 系統多用在伺服器或工作站,家用電腦上不太有機會用到。比較易於取得的則是類 Unix 系統,像是 macOS 或 GNU/Linux 等。

在類 Unix 系統中,macOS 的桌面環境做得最好,約略可取代 Windows 八成到九成的功能,而且有不少商業軟體可用。但 macOS 主機較貴,幾乎不會為了學 Unix 系統特地去買。

GNU/Linux 不是單一的作業系統,而是數種使用 Linux 核心的系統。由於 GNU/Linux 由自由軟體組成,給開發者高度自訂性,有許多團隊針對各種不同用途開發出不同的 GNU/Linux 發行版,像是適用合桌面環境的系統或是伺服器用系統。

GNU/Linux 系統本身免費,但要找到適合的硬體,才不會有硬體無法驅動的問題。可參考 Ubuntu 認證的家用電腦清單,比較不會踩到雷。台灣也有獨立商為製作音樂所打造的 GNU/Linux 筆電,可當成一般的類 Unix 系統來用。

BSD 系統則是另一大類的類 Unix 系統,比較常見的是 FreeBSD 或 TrueOS。但 BSD 系統相關的線上資料比較少,一開始不建議直接從 BSD 系統入門。

在 Windows 上,還有 Cygwin 或 WSL (Windows Subsystem for Linux) 等類 Unix 子系統可用。但這些子系統和實際的類 Unix 系統比起來仍有一些差別,有時候會碰到一些非常規的小問題,故筆者不建議只用這些子系統來學 Unix 和 shell 程式。

在虛擬環境中使用類 Unix 系統

如果還不想購買實體機器,可在 VirtualBox 等虛擬機器中安裝 GNU/Linux (或其他類 Unix 系統) 來用。雖然虛擬機器的運行速度和實體機器相比差了一些,不常用類 Unix 系統的話,可以省下一些費用。

若對 Unix 還不熟悉,可以先裝在虛擬機試跑看看,覺得好用才裝在實體機器上。此外,虛擬機器可以為系統建立快照 (snapshot),所以可以把虛擬機內的系統當成測試環境,測試完再將系統回復到快照點。

近年來,雲端運算興盛,像 AWS Cloud 9 這類結合網頁 IDE 和 GNU/Linux 虛擬機器的雲端軟體成為新的選擇。這類雲端 IDE 在開完新環境後,馬上有 IDE 和 GNU/Linux 環境可用,絕對會比自己安裝系統快得多。而且這類雲端軟體用多少花多少,不用時把系統殺掉即可,所以開銷不會太大。

Shell 不只一種

Shell 是通稱,因類 Unix 系統的 shell 不只一種,系統使用者可隨自己的喜好來更換命令列環境所用的 shell。根據 shell 程式的語法體系,約略可分為三種:

  • Bourne shell 系列
    • Sh shell (POSIX shell)
    • Bash shell
    • Ksh shell
    • Zsh shell
  • C shell 系列
    • Csh shell
    • Tcsh shell
  • 獨立開發的 shell
    • Fish shell

原本 Unix 使用的是 sh shell,相當於現在的 POSIX shell,後來 GNU 計畫寫了 Bash。Bash 除了相容於 POSIX shell 外,還加入了許多新的功能。目前 Bash 是類 Unix 系統上使用最廣的 shell。

Ksh 則是另一個增強版的 sh 相容 shell,但沒有 Bash 那麼普遍,而且 Ksh 和 Bash 互不相容。相對來說,Zsh 除了 (大部分) 相容於 Bash 外,還強化了交互性使用的體驗。

Csh 使用一套類似於 C 的語法,和 sh 不相容。Tcsh 則是 csh 的增強版。目前 Tcsh 是 FreeBSD 等系統的預設 shell,但 Tcsh 流行度不若 Bash。

除了這兩大體系外,還有一些不相容於 Bourne shell 和 C shell 的 shell,像是 Fish。由於沒有歷史包袱,Fish 等新興 shell 可以自由地加入比較新的設計。但這類新興 shell 並未成為主流。

在這麼多種 shell 程式裡,要如何選擇呢?基於流行度和相容性等因素,基本上筆者只建議 POSIX shell 或 Bash。因 sh 本身是 POSIX 標準,而 Bash 則是比較流行。

許多 shell scripting 教材會直接教 Bash,但筆者建議先試著寫純 POSIX shell,只有在必要時才轉用 Bash。因 Bash 向後相容 POSIX shell,但反之則否。

我們在寫 shell 程式時,把 shell 當成直譯器來用,所以平常使用的 shell 和寫 shell 程式的 shell 不需要用同一個。平常使用的 shell,可以用 Zsh、Fish 等有針對互動性加強的 shell。在寫 shell 命令稿時,考量系統間的相容性,最好還是用 POSIX shell 或 Bash 來寫。

選擇寫 Shell 程式的編輯器

Shell 算是輕量級語言,用一般的小型編輯器來寫就可以了。甚至像 nano(1) 這種簡易的命令列編輯器都可以用來寫 shell 命令稿。所以,只要選自己用得順手的編輯器即可。

Shell 程式沒有函式庫

主流語言都會有函式庫 (或物件庫),可藉由呼叫函式庫 (或物件庫) 的 API 來取得特定功能。但 shell 程式沒有函式庫可用,而是直接和命令列工具互動。透過各式各樣的工具來完成特定任務。

但 shell 可以用函式組織程式碼,而且可以引入其他 shell 命令稿。這些行為整體上很像是在引入外部函式庫。所以,雖然 shell 程式沒有真正的函式庫,我們還是可以為命令列環境和 shell 程式撰寫可重覆使用的函式。

儘量避開 AWK 或 Perl

在命令列工具中,不乏有 AWK 或 Perl 這種兼具命令列工具和程式語言的軟體。由於 AWK 或 Perl 本身具有程式語言的功能,使用起來會比其他沒有程式語言的工具來得靈活方便。但我們應謹慎地使用 AWK 或 Perl 這類大型工具,主要是效率上的考量。

AWK 或 Perl 這類工具,使用時需要解析和執行完整的程式語言,有時候還要加上讀入函式庫等動作,所以速度往往會比 grep(1) 這類小巧的工具來得慢。如果在 shell 命令稿中需要大量地呼叫 AWK 或 Perl,為什麼不乾脆直接以 AWK 或 Perl 來寫命令稿呢?

Shell 指令的種類

在 shell 程式中,指令可能有以下五種來源:

  • 保留字 (keywords)
  • 內建指令或函式 (shell builtin)
  • 別名 (alias)
  • 函式 (function)
  • 外部程式 (external program)

保留字是 shell 的語法,像是 ifforwhile 等。內建指令或函式則由 shell 本身附帶,不需安裝,像 Bash 的 cd 是內建指令。這兩者都是 shell 內建的功能。

別名是由使用者自定義的字串,用來取代現有的指令,像是為指令加上一些額外的參數。函式則是一段程式碼區塊,用來封裝一至多行指令,並用有意義的名稱來命名此區塊。別名和函式都是開放給使用者自訂的功能。

至於外部程式則是系統上可取得的命令列工具。這些工具可能是執行檔 (executable) 或命令稿 (script)。兩者的差別在於程式是以編譯語言或直譯語言實作而成。

對於 shell 程式來說,每執行一個外部程式,就會多開一個行程。相對來說,用內建功能不需另開行程。所以,當 shell 的效能很重要時,減少外部程式的量也是一個可能的方向。

結語

我們用了兩篇文章來介紹 shell 的特性,無非是希望讀者對 shell 能更加了解。在下一篇文章中,我們會開始寫第一個 shell 程式,以熟悉 shell 程式的開發流程。

分享本文
Facebook Twitter LinkedIn LINE Skype EverNote GMail Yahoo Yahoo
追蹤本站
Facebook Facebook Twitter