两种脚本语言的对比:Bash 与 Python

1,162 阅读6分钟

计算机是一种只能理解特定二进制指令的数字设备。没有操作系统,我们只能使用一些内置的固件,例如计算机中的 BIOS 实用程序。操作系统通过提供一种方法来执行预先开发的程序(即文字处理器、网络浏览器和实用程序),从而使计算机可供人们使用。现在大多数操作系统都允许用户使用 GUI(图形用户界面)和 CLI(命令行界面)。

程序员通常喜欢使用 CLI,因为使用 CLI 比使用 GUI 更接近于日常编程活动。他们经常通过 CLI 部署软件、执行文件系统操作和配置计算机系统。CLI 是执行所有任务的高效方式,但我们通常必须运行输入的相同命令并稍作修改。

因此,CLI 解释器提供了 shell 脚本概念来从文件运行预先编写的命令。Bash 是一种众所周知的、传统的、内置的(在大多数操作系统中)用于运行 shell 脚本的命令语言。另一方面,许多程序员使用 Python 作为 shell 脚本的替代品,它具有 Bash 不(从不)提供的内置功能。

在这个故事中,我将从 shell 脚本的角度比较 Bash 和 Python,并为您解释一些鲜为人知的 shell 脚本技术,以提高您使用 Bash 和 Python 的自动化技能。

Bash:最自然的 shell 脚本编写方式

shell 脚本背后的主要思想是使用 shell 解释器运行预先编写的命令序列。Bash 将每个输入/语句视为一个命令,并提供了一种高效的自动化方式。还记得你第一天使用基于 Bash 的终端(也许是在上大学的时候吗?)而没有阅读文档或遵循教程:

回忆你第一次基于 Bash 的终端体验,作者截图

Bash 并不是一种通用的通用语言——它总是激励您使用其他程序。例如,您可能会使用expr 10 + 15上述场景。但是,现代 Bash 支持一般编程要求的内置功能,因此在某些情况下您不需要调用其他程序。

例如,它允许您通过算术扩展功能进行基本算术运算:

在终端中使用算术展开,笔者截图

Bash 在没有专用扩展语法的情况下以本机方式执行命令,并为通用编程需求提供最小语法。

Python:解决 Bash 缺失功能的现代方法

如果 Bash 本机执行命令并支持许多通用编程功能,为什么程序员要使用 Python 进行自动化?请参阅以下非常早期版本的Python 历史文档:

根据该文档,最初开发 Python 是为了将 shell 脚本与本机操作系统级编程相结合。Bash 无法在本地访问操作系统级 API(也称为 C API)。因此,如果自动化脚本需要访问 C API,程序员必须使用变通方法,例如使用另一种编程语言创建可执行文件。Python 通过提供一种具有 C API 访问权限的自动化友好的最小语言解决了这个问题——甚至使用跨平台的方式来访问操作系统级 API。

Python 从通用编程的角度评估源代码,因此它无法在本地执行其他程序,但提供了对开发人员友好的子进程 API

我们检查了语言的目标和基础知识。让我们开始比较吧!

Bash 与 Python:哪个更适合自动化?

程序员编写各种 shell 脚本。有时,他们会编写执行多个 POSIX 命令(即mvcp等)的 shell 脚本。在某些情况下,他们需要在 shell 脚本中包含数据处理和操作系统级操作。此外,有时他们需要编写跨平台的自动化脚本。

与几乎所有现代编程语言比较总结一样,这里没有赢家——最佳的 shell 脚本选项取决于我们的开发场景。

Bash 适用于以下场景:

  • 自动化涉及较少数据处理的 POSIX 命令行操作,即系统管理脚本
  • 编写通过其他 CLI 程序执行配置、处理或杂项操作的 shell 脚本,即编写Git提交消息并通过 CLI 工具进行应用程序部署
  • 如果您希望您的脚本在 Unix 系统上具有更高的可移植性,Bash 是一个不错的选择,因为 Bash 解释器比 Python 预装得更广泛

Python 适用于以下场景:

  • 与执行其他 CLI 程序相比,自动化涉及更多数据处理(算法操作)和访问低级 API 的任务
  • 编写执行命令的跨平台自动化脚本,使用低级 API,并在 GNU/Linux、Windows、macOS 和其他支持 Python 的操作系统上进行通用数据处理。请参阅BuildZri 源代码作为示例项目。

总体而言,Bash 是与其他命令行程序一起编写自动化脚本的最精简、自然、本机和类似于终端的方式。另一方面,Python 是一种跨平台的通用语言,您可以将其用作 Bash 的替代品,用于编写具有低级操作系统 API 访问和数据处理功能的 shell 脚本。

一起使用 Bash 和 Python!

Bash 和 Python 之间没有激烈的竞争,因为它们是两种不同的编程语言类型——Bash 是一种命令语言,而 Python 是一种通用语言。我们可以根据需要选择一个选项,也可以同时使用两者。

假设您使用bc如下方式添加两位小数:

#!/bin/bash 

sum =$(bc <<< "1.5 + 2.51" ) 
echo  $sum

您可以使用 Python 来做同样的事情:

#!/bin/bash 

sum =$(python3 <<< "print(1.5 + 2.51)" ) 
echo  $sum

正如许多程序员在他们的 Python 脚本中所做的那样,在 Python 中使用 Bash 也是比使用许多第三方 Python 包更方便的选择。例如,查看以下脚本如何找到 Gedit 程序的进程标识符:

#!/usr/bin/env python3 

import subprocess 

gedit_pid = subprocess \ 
              .getoutput( "ps -ef | grep gedit | head -1 | awk '{print $2}'" ) \ 
              .strip() 
print (gedit_pid)

为现代自动化解决 Bash 和 Python 中的问题

正如我们所讨论的,Bash 和 Python 对于现代自动化要求都有一些缺点。使用 Bash 很难编写具有操作系统级 API 访问和复杂数据处理的 shell 脚本。使用 API 在 Python 中编写最小的命令行程序执行在语法上不像 shell subprocess

如果需要在 Bash 中使用 C API,可以使用ctypes.shBash 扩展:

ctypes.sh,bash 的外部函数接口,下载ctypes.sh的源码_GitHub_帮酷

这是 ctypes.sh,bash 的外部函数接口。ctypes.sh 是一个提供外部函数的 bash 插件……

github.com

甚至还有一个使用外部函数接口 ( FFI )httpd.sh用 Bash 编写的 HTTP Web 服务器。ctypes.sh

pysh项目提供了一种使用字符在 Python 脚本中执行 Bash 语句的简单方法>,如以下代码片段所示:

for i in xrange( 100 ): 
   index = "%02d" % i 
   > mv从$index.txt 到 $index.txt

zxpy项目(受 Google 的启发zx)允许您使用 Python 高效地执行命令行操作,如下所示:

#!/usr/bin/env zxpy
 ~ 'echo Hello world!' 

文件计数 = ~ 'ls -1 | wc -l' 
print ( "文件数是:" , file_count)

结论

shell 脚本概念始于1970 年代左右历史悠久的Unix 环境的Thompson shell。传统 shell 脚本背后的想法是从文件执行命令行操作以实现自动化。现代 DevOps 运动通过在自动化脚本中包含 RESTful API 调用、数据处理和其他与 DevOps 相关的操作,扩展了传统的 shell 脚本概念。

使用 Bash 作为 shell 脚本选项对于现代自动化来说并不过时,因为它允许您在没有单独的子进程 API 的情况下本地执行命令(它是本地包含的)。如果程序员执行比本机命令行操作更多的其他操作,他们通常会使用 Python 作为现代 Bash 的替代方案来实现自动化。