对于Linux用户而言,命令行操作咱们曾经十分相熟了。与其余风行的操作系统不同,在Linux社区中,应用命令行与应用图形用户界面执行相似工作相比,命令行通常能够提供更优雅,更无效的解决方案。

随着Linux社区对命令行的依赖一直增长,UNIX shell(如bash和zsh)已倒退成为极其弱小的工具,能够补充UNIX shell的教训。应用bash和其余相似的shell,能够应用许多弱小的性能,例如管道,文件名通配符以及从称为脚本的文件中读取命令的性能。

让咱们看一个实在的示例来演示命令行的性能。每次用户登录服务时,其用户名都会记录到一个文本文件中。对于此示例,让咱们找出有多少惟一用户应用该服务。

以下示例中的一系列命令通过将较小的构建块链接在一起,显示了更简单的实用工具的性能:

$ cat names.log | sort | uniq | wc -l

管道符号(|)用于将一个命令的规范输入传递到下一命令的规范输出。在此处的示例中,cat names.txt的输入传递到sort命令中。sort命令的输入是按字母程序重新排列文件的每一行。随后将其传递给uniq命令,该命令将删除所有反复的名称。最初,uniq的输入传递到wc命令。wc是计数命令,并且设置了-l标记,它返回行数。这使您能够将许多命令链接在一起。

然而,有时所需的内容可能会变得非常复杂,并且将命令链接在一起可能变得蠢笨。在这种状况下,shell脚本就是答案。Shell脚本是由Shell读取并按程序执行的命令列表。Shell脚本还反对某些编程语言基础知识,例如变量,流控制和数据结构。Shell脚本对于将常常反复运行的批处理作业十分有用。可怜的是,shell脚本有一些毛病:

Shell脚本很容易变得过于简单,并且对于想要改良或保护它们的开发人员来说是不可读的。

这些shell脚本的语法和解释器通常很蠢笨且不直观。语法越蠢笨,对于必须应用这些脚本的开发人员来说,可读性就越差。

该代码通常无奈在其余脚本中应用。脚本之间的代码重用往往很艰难,并且脚本往往十分特定于某个问题。

用于高级性能(例如HTML解析或HTTP申请)的库不像古代编程和脚本语言那样容易取得。

这些问题会使shell脚本难以解决,并常常导致大量开发人员工夫节约。取而代之的是,Python编程语言能够用作十分无力的替代品。应用Python代替Shell脚本有很多益处:

默认状况下,所有次要的Linux发行版都装置了Python。关上命令行并立刻键入python,将使您进入Python解释器。这种普遍性使它成为大多数脚本工作的理智抉择。

Python具备十分易于浏览和了解的语法。它的格调强调简洁和简洁的代码,同时容许开发人员以适宜shell脚本的准系统格调进行编写。

Python是一种解释型语言,这意味着没有编译阶段。这使Python成为编写脚本的现实语言,它容许您以解释的形式疾速尝试新代码。这使开发人员能够疾速批改,而不用将整个程序写到文件中。

Python是一种功能齐全的编程语言。代码重用很简略,因为Python模块能够轻松导入并在任何Python脚本中应用。脚本能够轻松扩大或构建。

Python能够应用杰出的规范库和数以千计的第三方库来解决各种高级实用程序,例如解析器和申请库。例如,Python的规范库包含日期工夫库,该库容许将日期解析为指定的任何格局并将其与其余日期轻松比拟。

但Python不应替换所有bash命令。编写以UNIX形式运行的Python程序(即读入规范输出并写入规范输入)与为现有的shell命令(如cat和sort)编写Python替代品一样弱小。

让咱们以本文后面已解决的问题为根底。除了曾经实现的工作之外,让咱们找出某个用户已登录零碎的次数。uniq命令仅删除反复项,但不提供无关有多少反复项的信息。代替uniq,Python脚本能够用作链中的另一个命令。这是一个执行此操作的Python程序(在我的示例中,我将此文件称为namescount.py):

#!/usr/bin/env pythonimport sysif __name__ == "__main__":    # Initialize a names dictionary as empty to start with.    # Each key in this dictionary will be a name and the value    # will be the number of times that name appears.    names = {}    # sys.stdin is a file object. All the same functions that    # can be applied to a file object can be applied to sys.stdin.    for name in sys.stdin.readlines():            # Each line will have a newline on the end            # that should be removed.            name = name.strip()            if name in names:                    names[name] += 1            else:                    names[name] = 1    # Iterating over the dictionary,    # print name followed by a space followed by the    # number of times it appeared.    for name, count in names.iteritems():            sys.stdout.write("%d\t%s\n" % (count, name))

让咱们看看这个Python脚本如何适宜命令链。首先,它从通过sys.stdin对象公开的规范输出中读取输出。任何输入都将写入sys.stdout对象,这是在Python中实现规范输入的形式。Python字典(在其余语言中通常称为哈希映射)用于获取从用户名到反复计数的映射。要取得所有用户的数量,请执行以下操作:

$ cat names.log | python namescount.py

显示用户呈现的次数以及用户名的计数。接下来要做的是按程序显示最常应用该零碎的用户。这能够在Python级别实现,然而让咱们应用外围UNIX实用程序曾经提供的实用程序来实现它。以前,我应用sort命令对字母进行排序。如果命令提供了-rn标记,它将按降序对行进行数字排序。随着Python脚本按规范输入,只需将命令通过管道传递到sort并检索所需的输入:

$ cat names.log | python namescount.py | sort -rn

这是将Python用作命令链一部分的弱小示例。在这种状况下应用Python的长处如下:

  • 与cat和sort等工具链接的能力。简略的实用程序(逐行读取文件并以数字形式对文件进行排序)由久经考验的UNIX命令解决。这些命令也逐行读取,这意味着这些性能能够缩放到大型文件,而且速度很快。
  • 当须要在链中进行一些沉重的工作时,能够编写一个十分清晰,简洁的Python脚本,该脚本将执行其所需的工作,而后将责任转移给链中的下一个链接。
  • 它是一个可重用的模块,只管此示例专门针对名称,然而如果您向此输出中蕴含反复行的任何输出,它将打印出每行和反复的数量。通过将Python代码模块化,能够将其利用于各种场景。

为了展现以模块化和管道形式组合Python脚本的弱小性能,让咱们进一步把问题放大。让咱们找到该服务的前五名用户。head是一个命令,它容许您指定肯定数量的行以显示给定的规范输出。将其增加到命令链中将失去以下内容:

$ cat names.log | python namescount.py | sort -rn | head -n 5

这仅显示前五个用户,而疏忽其余用户。同样,要使五个用户起码应用该服务,能够应用tail命令,该命令采纳雷同的参数。将Python命令打印到规范输入的后果使能够构建和扩大其性能。

以上就是简略的介绍,理论中大家灵活运用就好。