跳轉到內容

Shell 程式設計/入門

來自華夏公益教科書,開放的書籍,開放的世界


上一頁:Shell 程式設計 索引 下一頁:什麼是 shell


一個 shell 指令碼 是一個由 Unix shell,一個 命令列直譯器 執行的程式。簡單來說,它是一系列要執行的命令,就像在命令列中輸入一樣,可以作為一個單獨的命令呼叫 - 它是一個“指令碼”,供 shell 執行。這樣可以避免重複輸入,簡化呼叫,並允許指令碼像任何其他程式一樣使用,包括被其他 shell 指令碼或其他程式呼叫。從 shell 的角度來看,指令碼是一系列它執行的命令;從另一個程式的角度來看,指令碼只是一個可以像任何其他程式一樣執行的程式。更正式地說,shell 語言是 shell 的 指令碼語言,隱含地也是主機作業系統的指令碼語言:它們允許人們輕鬆地呼叫命令。

除了簡單地列出命令之外,shell 通常還提供程式語言功能,例如變數和控制流結構,因此允許將複雜程式編寫為指令碼。原則上,任何指令碼都可以在命令列中輸入 - “指令碼”和 shell 命令序列之間沒有根本區別 - 但除了簡短的結構(例如 for 迴圈)之外,通常不會這樣做。

基本的 shell 指令碼非常容易編寫:只需使用 shell 會話的轉錄即可。但是,與編譯程式(例如 C 程式)相比,shell 指令碼執行速度非常慢,甚至與呼叫庫而不是單獨程序的解釋程式(例如 Python 指令碼)相比,也很慢,並且很難將複雜程式編寫為 shell 指令碼。因此,它們主要適合那些廣泛呼叫作業系統(特別是檔案操作)或其他程式的冗長但簡單的任務,特別是在 系統管理 中。更復雜或對效能敏感的任務則用通用語言編寫,傳統上是 C,最近是 Perl 或 Python。由於易於編寫,shell 指令碼也非常適合一次性程式碼或快速原型設計,就像其他指令碼語言一樣,並且為使用者提供了一個非常好的入門,無論是通用的程式設計還是作業系統,特別是對於熟悉命令列的使用者。

本書介紹與 sh 相容的 shell。

存在各種 shell,它們的行為各不相同,因此這些 shell 都有不同的程式語言。大多數 shell 都是 Bourne shell (sh;見 Bourne Shell 指令碼編寫) 的變體,共享基本語法,但增加了功能,相關的程式語言被稱為 sh 的“方言”。如今,在 Linux 上最常見的是 bash,“Bourne-again shell”(見 Bash Shell 指令碼編寫),它是一個提供許多功能的複雜 shell。 Korn shell (ksh) 也被使用,主要是在專有 Unix 系統(根據 POSIX 標準)和 BSD 作業系統上。但是,也使用其他 shell,例如 Almquist shell (ash),特別是在資源受限的環境中,出於安全目的,或者為了許可 - 這些 shell 通常會省略互動式功能,使它們更小、更安全 - 編寫跨 sh 方言相容的指令碼稱為“可移植的 shell 指令碼”。可移植的 shell 指令碼編寫需要將自己限制在目標語言相容的功能子集中 - 這在很大程度上等同於將自己限制在原始 Bourne shell 語言中,但有一些微妙的邊緣情況需要注意。

C shell (csh) 及其變體是主要的非 sh 相容 shell。它也可以用指令碼編寫(見 C Shell 指令碼編寫),但這並不常見,因為該語言存在嚴重問題。 [1] 因此,csh 在 1980 年代和 1990 年代主要用作互動式 shell,與 sh 的一些變體一起用於指令碼編寫。由於 sh 相容的 shell 添加了 csh 的互動式功能,這種情況已經基本消失。因此,對於本書而言,shell 指的是 sh 相容的 shell。

應用程式

[編輯 | 編輯原始碼]

Shell 指令碼本質上是作業系統的指令碼語言,因此適合涉及呼叫作業系統工具(例如檔案操作)或多個其他命令的任務,邏輯和高階語言功能相對較少。相比之下,涉及複雜邏輯或呼叫很少其他命令的任務 - 或者可以呼叫庫而不是單獨命令 - 最好在通用語言中編寫,如今通常是高階語言,如 PythonRuby。早期的 Perl 就是為此目的而編寫的 - 更高階的 shell 指令碼編寫 - 並且保留了 shell 指令碼編寫的大部分風格和語法;它在 1980 年代後期到 2000 年代初期非常流行,但此後人氣下降。

Shell 指令碼編寫的主要應用是自動化重複任務或編寫一次性指令碼以完成複雜的一次性任務。Shell 指令碼編寫是 系統管理 中的一項關鍵技能,也用於為程式或程式組合編寫指令碼,前提是存在良好的命令列介面,但沒有內建的指令碼語言或庫。

Shell 指令碼相對於其他語言的主要優勢是輕鬆呼叫其他命令,而無需冗長的語法(顯式函式呼叫和引用),而主要缺點是功能有限,語法笨拙且難以處理(特別是由於與互動式使用的相容性以及引用的緣故),以及執行速度慢(由於執行單獨程序的開銷,特別是 上下文切換)。

替代方案

[編輯 | 編輯原始碼]

與其使用執行單獨命令的 shell 指令碼,如果庫可用,可以編寫一個呼叫庫的程式,這樣可以避免單獨程序的時間開銷(以及空間開銷,如果動態連結),但代價是連結庫。這會產生其他成本:如果靜態連結,則需要在編譯時付出時間成本,磁碟上的空間成本以及執行時空間成本(由於包含庫);而如果動態連結,則需要在執行時付出時間成本,儘管動態連結每個庫只需要執行一次。

相反,對於非常簡單的命令,特別是單行命令,shell 別名可以避免執行單獨指令碼的開銷。例如,對於目錄列表快捷方式,別名

alias lsal='clear;ls -al'

比指令碼

#!/bin/sh
clear
ls -al

更快、更簡單。

參考資料
  1. [編輯 | 編輯原始碼]
華夏公益教科書