Bash vs. Python:現(xiàn)代 Shell 腳本編程的巔峰較量
一臺計算機是一種只能理解特定二進制指令的數(shù)字設(shè)備。在沒有操作系統(tǒng)的情況下,我們只能使用一些內(nèi)置的固件,比如計算機中的BIOS實用程序。操作系統(tǒng)通過提供執(zhí)行預(yù)開發(fā)程序(例如文字處理器、網(wǎng)絡(luò)瀏覽器和實用工具)的方式,使計算機對人們可用?,F(xiàn)今的大多數(shù)操作系統(tǒng)允許用戶同時使用圖形用戶界面(GUI)和命令行界面(CLI)。
程序員通常喜歡使用命令行界面,因為與圖形用戶界面相比,使用命令行界面更貼近日常的編程活動。他們經(jīng)常通過命令行界面部署軟件、進行文件系統(tǒng)操作和配置計算機系統(tǒng)。命令行界面是一種高效完成所有任務(wù)的方式,但我們經(jīng)常需要運行稍作修改的相同命令。
因此,命令行界面解釋器提供了一種從文件中運行預(yù)先編寫的命令的shell腳本概念。Bash是一種著名的傳統(tǒng)的內(nèi)置(在大多數(shù)操作系統(tǒng)中)命令語言,用于運行shell腳本。另一方面,許多程序員使用Python作為shell腳本的替代方案,它提供了Bash所沒有的內(nèi)置功能。
在本文中,我將從shell腳本的角度比較Bash和Python,并解釋一些較少為人所知的shell腳本技巧,以幫助您提高使用Bash和Python進行自動化的技能。
Bash:最自然的shell腳本方式
Shell腳本的主要思想是使用shell解釋器運行預(yù)先編寫的命令序列。Bash將每個輸入/語句都視為一個命令,并提供了一種高效的自動化方式。還記得第一次使用基于Bash的終端(也許是在大學(xué)時?)而沒有閱讀文檔或跟隨教程的經(jīng)歷嗎?
回想起您第一次使用基于Bash的終端的經(jīng)歷,作者提供的截圖 Bash并不作為一種通用的通用編程語言,它總是鼓勵您使用其他程序。例如,您可以在上述情況下使用”expr 10 + 15″。然而,現(xiàn)代的Bash支持內(nèi)置功能,用于滿足一般編程需求,因此在某些情況下,您無需調(diào)用其他程序。
例如,它通過算術(shù)擴展功能讓您執(zhí)行基本的算術(shù)運算:
在終端中使用算術(shù)擴展,作者提供的截圖 Bash可以原生地執(zhí)行命令,無需專用的擴展語法,并為通用編程需求提供了簡潔的語法。
Python: 一種現(xiàn)代化的方式,解決了Bash中的一個缺失功能
如果Bash可以原生執(zhí)行命令并支持許多通用編程功能,那為什么程序員要使用Python進行自動化呢?看一下下面來自早期版本Python文檔的歷史資料:
用LaTeX編寫的Python文檔的早期版本
根據(jù)這份文檔,Python最初的開發(fā)目標是將shell腳本與本地操作系統(tǒng)級編程結(jié)合起來。Bash無法原生訪問操作系統(tǒng)級API(也稱為C API)。因此,如果自動化腳本需要訪問C API,程序員必須使用其他編程語言創(chuàng)建一個可執(zhí)行文件來實現(xiàn)。Python通過提供一個友好的、簡潔的語言并具備C API訪問權(quán)限來解決了這個問題,甚至還提供了一種跨平臺的訪問操作系統(tǒng)級API的方式。
Python從通用編程的角度評估源代碼,因此它不能原生執(zhí)行其他程序,但提供了一個開發(fā)者友好的子進程API。
我們已經(jīng)對這兩種語言的目標和基礎(chǔ)知識進行了檢查?,F(xiàn)在讓我們開始進行比較吧!
Bash vs. Python: 哪個更適合自動化?
程序員編寫各種各樣的shell腳本。有時候,他們編寫的shell腳本執(zhí)行一些POSIX命令(例如mv,cp等)。在某些情況下,他們需要在shell腳本中包含數(shù)據(jù)處理和操作系統(tǒng)級操作。此外,有時候他們需要編寫跨平臺的自動化腳本。
和幾乎所有現(xiàn)代編程語言的比較總結(jié)一樣,這里沒有贏家——最佳的shell腳本選項取決于我們的開發(fā)場景。
Bash適用于以下情況:
- 自動化涉及較少數(shù)據(jù)處理的POSIX命令行操作,例如系統(tǒng)管理腳本
- 通過其他CLI程序執(zhí)行配置、處理或其他操作的shell腳本,例如通過CLI工具編寫Git提交信息和進行應(yīng)用部署
- 如果您希望腳本在Unix系統(tǒng)上具有更好的可移植性,Bash是一個不錯的選擇,因為Bash解釋器的預(yù)安裝范圍比Python更廣泛
Python適用于以下情況:
- 自動化涉及更多數(shù)據(jù)處理(算法操作)和訪問低級API,而不僅僅是執(zhí)行其他CLI程序
- 編寫跨平臺自動化腳本,在GNU/Linux、Windows、macOS和其他Python支持的操作系統(tǒng)上執(zhí)行命令、使用低級API并進行通用數(shù)據(jù)處理。以BuildZri項目為例。
總的來說,Bash是使用其他命令行程序編寫自動化腳本的最簡潔、自然、本地化和類似終端的方式。另一方面,Python是一種跨平臺的通用編程語言,您可以將其作為Bash的替代方案,用于編寫具有低級操作系統(tǒng)API訪問和數(shù)據(jù)處理功能的shell腳本。
Bash和Python一起使用
Bash和Python之間并不存在極端的競爭,因為它們是兩種不同的編程語言類型——Bash是一種命令語言,而Python是一種通用編程語言。我們可以根據(jù)需求選擇其中一種選項,或者同時使用兩種語言。
假設(shè)您使用bc來執(zhí)行兩個小數(shù)的加法,代碼如下:
#!/bin/bash
# Linux迷 www.linuxmi.com
sum=$(bc <<< "1.65 + 2.91")
echo $sum
您也可以使用Python完成相同的任務(wù),代碼如下:
#!/bin/bash
sum=$(python3 <<< “print(1.5 + 2.51)”) echo $sum
與許多程序員在Python腳本中所做的一樣,使用Bash在Python中也是比使用許多第三方Python包更方便的選擇。例如,看看下面的腳本如何查找Gedit程序的進程標識符:
#!/usr/bin/env python3
# Linux迷 www.linuxmi.com
import subprocess
gedit_pid = subprocess \
.getoutput("ps -ef | grep gedit | head -1 | awk '{print $2}'") \
.strip()
print(gedit_pid)
解決現(xiàn)代自動化中的Bash和Python問題
正如我們討論過的,Bash和Python在現(xiàn)代自動化需求中都存在一些缺點。使用Bash編寫具有操作系統(tǒng)級API訪問和復(fù)雜數(shù)據(jù)處理的shell腳本很困難。而使用Python的subprocess API執(zhí)行最小化的命令行程序不具備與Shell語法相似的語法特性。
如果您需要在Bash中使用C API,可以使用ctypes.sh Bash擴展:https://github.com/taviso/ctypes.sh
甚至還有一個使用ctypes.sh外部函數(shù)接口以Bash編寫的名為httpd.sh的HTTP Web服務(wù)器。
pysh 項目提供了一種在Python腳本中使用”>”字符執(zhí)行Bash語句的簡單方法,如下面的代碼片段所示:
for i in xrange(100):
index = "%02d" % i
> mv from$index.txt to$index.txt
zxpy項目(受Google的zx啟發(fā))可以讓您以以下方式在Python中高效執(zhí)行命令行操作:
#! /usr/bin/env zxpy
# Linux迷 www.linuxmi.com
~'echo Hello world!Linux迷 www.linuxmi.com'
file_count = ~'ls -1 | wc -l'
print("file count is:", file_count)
總結(jié)
Shell腳本的概念始于20世紀70年代左右的Unix環(huán)境中的歷史Thompson shell。傳統(tǒng)Shell腳本的想法是從文件中執(zhí)行命令行操作,用于自動化目的?,F(xiàn)代DevOps運動通過在自動化腳本中包含RESTful API調(diào)用、數(shù)據(jù)處理和其他與DevOps相關(guān)的操作,擴展了傳統(tǒng)的Shell腳本概念。
在現(xiàn)代自動化中,使用Bash作為Shell腳本選項并不過時,因為它允許您以本地方式執(zhí)行命令,無需單獨的子進程API(它已經(jīng)內(nèi)置)。如果程序員在自動化中需要執(zhí)行的操作超出了本地命令行操作,他們通常會使用Python作為現(xiàn)代的Bash替代方案。