跳转至内容

Unix/我的第一个Shell脚本快速入门

来自Wikibooks,开放世界中的开放书籍


什么是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脚本书中了解更多关于脚本编写的知识。

华夏公益教科书