Unix/我的第一個Shell指令碼快速入門
到目前為止,我們一直在Shell提示符處發出Unix命令。這是一種非常直接的工作方式,但在某些情況下並不理想。假設您有一個以特定複雜方式處理的檔案 - 將其內容置於一系列不同的Unix程序中?您可以使用管道和重定向在命令列上執行此操作,但如果出錯,則可能需要重新開始。(當然,第一次嘗試複雜過程時,您是在副本資料檔案上工作,對吧?)。如果您需要經常執行此操作,也許是定期執行,並且每次都必須逐個命令地執行該過程,這也會很煩人,並且這樣做會帶來打字錯誤的機會。
幸運的是,Unix提供了一種非常簡單的方法來避免這些情況。您可以建立一個包含Unix命令的文字檔案;為其指定一個副檔名為.sh的檔名,然後透過在命令提示符下呼叫此檔名來執行所有這些命令。讓我們從一個非常簡單的例子開始。
在pico編輯器中,建立一個包含以下文字的檔案,完全按照此處顯示的方式。
#!/usr/bin/bash ls -l .*
將此檔案儲存在您的主目錄中,命名為hid.sh。我們將像使用命令一樣在命令列中使用此指令碼。這將列出所有以點開頭的檔案和目錄(及其內容)(也就是說,隱藏的檔案和目錄)。指令碼中的第一行(在此上下文中,感嘆號稱為“bang”,因此第一行以hash bang開頭,也稱為shebang)確保Unix可以找到執行此檔案的Shell。
在執行它之前,我們必須處理此檔案上的許可權,以便可以執行它。Unix預設不允許執行檔案(這是一件非常好的事情)。使檔案可執行的命令是
% chmod 755 hid.sh
(我在這裡使用了簡寫 - 755 - 來設定組和其他人讀取和執行的許可權,以及所有者寫入、讀取和執行的許可權)。
現在您可以只通過在提示符處呼叫檔名來執行檔案中的命令
% ./hid.sh
(我必須鍵入./,因為此檔案不在當前路徑中。目前,我想忽略此複雜情況 - 它與Shell指令碼無關,而與Unix環境變數有關)。
為了說明一個更有趣的Shell指令碼,我將處理一個名為science.txt的檔案。我透過從維基百科關於科學的文章中刪除所有影像和格式來建立此檔案。當然,歡迎您嘗試相同的操作。
從“真正的Unix指令碼”的角度來看,我接下來要做的事情有點不自然。Unix高階使用者不會建立我下面建立的那種Shell檔案,但絕對會在命令列上直接使用grep輸出的管道和重定向。但是我在這裡的目標是令人驚歎,希望能激發靈感,並傳授一些知識。所以,學習並傳遞下去。
讓我們假設您是一位思想史學家。您想知道維基百科如何呈現科學思想的發展。首先,我們只檢視維基百科關於科學的文章中實際包含“科學”一詞的行(如上所述,我使用的是一個僅包含文章中未格式化文字的檔案)。我們如何使用我們所知道的Unix來找到這些行?答案,我相信您已經知道,是使用grep。要查詢所有包含“科學”一詞的行,我們將發出以下命令
% grep 'science' science.txt
所以現在建立一個文字檔案,在shebang指令之後的第一行中包含此命令。您可以將其命名為scisearch.sh。儲存檔案並更改許可權後,對其進行測試。它是否按預期執行?如果未按預期執行,請更正它;如果已按預期執行,請繼續。
這可能會很有趣。但是,與其只是將結果顯示在螢幕上,不如將它們儲存到檔案中更有用。我們可以使用重定向來實現。開啟檔案scisearch.sh並將其更改為以下內容
grep 'science' science.txt > scioutput.txt
進行此更改後,進行測試,如有必要,再次修改您的檔案。
現在,這已經是一個有趣的檔案,並且它說明了Shell指令碼的一些內容,但我們可以對其進行改進。目前,搜尋區分大小寫,因此將其更改為以下內容
grep -i 'science' science.txt > scioutput.txt
以便它不僅查詢science,還查詢Science。像往常一樣,您應該進行測試。您可能可以在沒有測試最後一次更改的情況下繼續,但在現實生活中,在每次更改後測試指令碼確實是一個好主意,以便在問題變得太難解決或除錯(行話)之前快速解決它們。
還有一個最終的修改建議本身。讓我們新增行號,以便如果我們想檢查對搜尋詞的引用上下文,我們可以輕鬆地找到它。
grep -in 'science' science.txt > scioutput.txt
(當然,現在您可以使用原始副本的副本,其中包含行號 - 您可以使用cat -n和輸出的重定向來實現此目的)現在您應該檢查檔案scioutput.txt - 使用less或使用Pico開啟它 - 以檢視內容是否符合您的預期。
這是一個相當簡單的Shell指令碼。它的唯一真正目的是說明建立指令碼檔案的通用原理。但是,我認為花一點時間思考一下如何在Microsoft Windows中執行此操作是值得的。
我們的指令碼按原樣使用是可以的,但它非常專業化。假設有一天我想對一個關於宗教的檔案執行類似的過程。一種方法是建立一個新的Shell指令碼,其中包含不同的檔案和搜尋詞。但這並不是最佳方法。更好的方法是對現有指令碼進行引數化或泛化。
Shell為您提供了一些變數名來表示位置引數。這些是值,可以根據鍵入的順序從命令列替換到指令碼中。變數$0保留給指令碼的名稱。我們現在不需要它。相反,我們將使用三個編號的變數來分別表示資料處理的搜尋字串、輸入檔案和輸出檔案。在指令碼中,它們將分別稱為$1、$2和$3。
修改您的指令碼檔案,使其內容如下
grep -in $1 $2 > $3
那麼我們如何使用這個新版本呢?在命令列中,我們用術語替換變數名。我們可以輸入
scisearch.sh 'religion' religion.txt reloutput.txt
這段程式碼假設我們在檔案religion.txt中搜索字串religion,並將輸出傳送到reloutput.txt。在許多Unix版本中,您可以繼續使指令碼更有趣——例如,透過為輸出新增上下文,例如不僅捕獲單個行,還捕獲其前後的行,但我們這裡不再贅述。現在最好重新命名我們的指令碼,因為它與科學不再有任何特別的關係。
這個新指令碼仍然只介紹了最基本的指令碼編寫理念,但您現在或許可以開始閱讀更詳細的Unix入門指南了。
您可以在Bourne Again Shell指令碼書中瞭解更多關於指令碼編寫的知識。
