Shebang
在計算領域中,Shebang(也稱為Hashbang)是一個由井號和驚嘆號構成的字元序列#!
,其出現在文字檔案的第一行的前兩個字元。
在檔案中存在Shebang的情況下,類Unix作業系統的程式載入器會分析Shebang後的內容,將這些內容作為直譯器指令,並呼叫該指令,並將載有Shebang的檔案路徑作為該直譯器的參數[1][2]。
例如,以指令#!/bin/sh
開頭的檔案在執行時會實際呼叫/bin/sh程式(通常是Bourne shell或相容的shell,例如bash、dash等)來執行。這行內容也是shell指令碼的標準起始行。
由於#
符號在許多手稿語言中都是註釋識別碼,Shebang的內容會被這些指令碼直譯器自動忽略。
在#
字元不是註釋識別碼的語言中,例如Scheme,直譯器也可能忽略以#!
開頭的首行內容,以提供與Shebang的相容性[3]。
"Shebang"或者說"Hashbang"的名字有時也被當做Ajax應用程式中的分段識別碼,用於瀏覽器的狀態儲存;Google網站站長中心提到,以驚嘆號開頭的分段識別碼(即...url#!state...)會為Google的網頁爬蟲所索引。
語法
Shebang這一語法特性由#!
開頭,即井號和驚嘆號。
在開頭字元之後,可以有一個或數個空白字元,後接直譯器的絕對路徑,用於呼叫直譯器。
在直接呼叫指令碼時,呼叫者會利用Shebang提供的資訊呼叫相應的直譯器,從而使得指令碼檔案的呼叫方式與普通的可執行檔案類似。
詞源與歷史
Shebang的名字來自於SHArp和bang,或haSH bang的縮寫,指代Shebang中#!
兩個符號的典型Unix名稱。
Unix術語中,井號通常稱為sharp,hash或mesh;而驚嘆號則常常稱為bang。也有看法認為,shebang名字中的sh來自於預設shell————Bourne shell的名稱,sh
,因為常常使用shebang呼叫之。[4][1]
在2010年版的Advanced bash scripting guide(頁面存檔備份,存於互聯網檔案館)(revision 6.2)中,shebang被稱為"sha-bang",同時提到"也寫作she-bang或sh-bang",但該檔案中沒有提到"shebang"這一形式。[1]
丹尼斯·里奇在被問及他會如何稱呼這一特性時,他答道:
發信人:"Ritchie, Dennis M (Dennis)** CTR **" <dmr@[redacted]>
收信人:<[redacted]@talisman.org>
日期:Thu, 19 Nov 2009 18:37:37 -0600
主題:RE: What do -you- call your #!<something> line?
我不記得我們曾經給它取過一個適當的名字。匯入這一特性已經是相當晚了--我覺得我是從關於伯克利Unix的UCB會議上的某人那裏得到的這一靈感;我可能是首先實現它的人之一,但這個創意是來自於別人的。
至於它的名字:可能是類似於"hash-bang"的英國風描述性文字,但我沒有在任何場合使用類似寵物的名字來描述它。
此致,
Dennis
例子
下面列出了一些典型的 shebang 直譯器指令:
#!/bin/sh
—使用sh
,即Bourne shell或其它相容shell執行指令碼#!/bin/csh
—使用csh
,即C shell執行#!/usr/bin/perl -w
—使用帶警告的Perl執行#!/usr/bin/python -O
—使用具有代碼最佳化的Python執行#!/usr/bin/php
—使用PHP的命令列直譯器執行
在許多系統上,/bin/sh
軟連結或硬連結到Bash,而/bin/csh
則連結到tcsh,因此設定前面的直譯器實際上是執行的與之相容的,或改進的版本。
Shebang行也可以包含需要傳遞到直譯器的特定選項(見下文的Perl例子)。然而,選項傳遞的方式隨實現的不同而不同。
用途
直譯器指令允許指令碼和數據檔案充當系統命令,無需在呼叫時由用戶指定直譯器,從而對用戶和其它程式隱藏其實現細節。
假設/usr/local/bin/foo
中有一以下行開頭的Bourne shell指令碼
#!/bin/sh -x
而它被如此呼叫("$"是命令提示符)
$ foo bar
該命令的輸出等同於
$ /bin/sh -x /usr/local/bin/foo bar
除了argv[0]被設定為指令碼的檔名,而非直譯器的檔名外。
由於sh
從其命令列指定的檔案中讀取命令,上面的命令就會執行/usr/local/bin/foo
中的命令,同時,將bar
作為foo
命令的參數$1
。
由於shebang開頭的井號也是Bourne shell和許多其它解釋性語言的註釋符,因此在這些語言中,直譯器指令本身會被直譯器認為是單純的註釋而跳過。
然而,並不是每一種直譯器都會自動忽略shebang行,例如對於下面的指令碼,cat
會把檔案中的兩行都輸出到標準輸出中。
#!/bin/cat
Hello world!
使用#!/usr/bin/env 脚本解释器名称
是一種常見的在不同平台上都能正確找到直譯器的辦法。
Linux的作業系統的檔案一般是UTF-8編碼。如果指令碼檔案是以UTF-8的BOM(0xEF 0xBB 0xBF)
開頭的,那麼exec函數將不會啟動shebang指定的直譯器來執行該指令碼。因此,Linux的指令碼檔案不應在檔案開頭包含UTF-8的BOM。
參見
- CrunchBang Linux,一種GNU/Linux發行版
- 檔案關聯
參考文獻
- ^ 1.0 1.1 1.2 Advanced Bash Scripting Guide: Chapter 2. Starting Off With a Sha-Bang. [2019-12-10]. (原始內容存檔於2019-12-10).
- ^ execve(2) - Linux man page. [2010-10-21]. (原始內容存檔於2010-11-02).
- ^ Martin Gasbichler and Michael Sperber. SRFI 22: Running Scheme Scripts on Unix. [2011-03-19]. (原始內容存檔於2011-02-27).
- ^ Jargon File entry for shebang. Catb.org. [2010-06-16]. (原始內容存檔於2011-06-04).
外部連結
- Details about the shebang mechanism on various Unix flavours(頁面存檔備份,存於互聯網檔案館)
- #! - the Unix truth as far as I know it(頁面存檔備份,存於互聯網檔案館)(a more generic approach)
- FOLDOC shebang article