一直学一直嗨,一直嗨一直学

Shell模块化(source命令)

所谓模块化,就是把代码分散到多个文件或者文件夹。对于大中型项目,模块化是必须的,否则会在一个文件中堆积成千上万行代码,这简直是一种灾难。

基本上所有的编程语言都支持模块化,以达到代码复用的效果,比如,Java和Python中有import,C/C++中有#include。在Shell中,我们可以使用 source命令来实现类似的效果。

在《执行Shell脚本》一节中我们已经提到了source命令,这里我们再来讲解一下。

source命令的用法为:

sourcefilename

也可以简写为:

.filename

两种写法的效果相同。对于第二种写法,注意点号.和文件名中间有一个空格。

source是Shell内置命令的一种,它会读取filename文件中的代码,并依次执行所有语句。你也可以理解为,source命令会强制执行脚本文件中的全部命令,而忽略脚本文件的权限。

实例

创建两个脚本文件func.sh和main.sh:func.sh中包含了若干函数,main.sh是主文件,main.sh中会包含func.sh。

func.sh文件内容:

#计算所有参数的和functionsum(){localtotal=0fornin$@do((total+=n))doneecho$totalreturn0}

main.sh文件内容:

#!/bin/bashsourcefunc.shecho$(sum10205515)

运行main.sh,输出结果为:
100

source后边可以使用相对路径,也可以使用绝对路径,这里我们使用的是相对路径。

避免重复引入

熟悉C/C++的读者都知道,C/C++中的头文件可以避免被重复引入;换句话说,即使被多次引入,效果也相当于一次引入。这并不是#include的功劳,而是我们在头文件中进行了特殊处理。

Shellsource命令和C/C++中的#include类似,都没有避免重复引入的功能,只要你使用一次source,它就引入一次脚本文件中的代码。

那么,在Shell中究竟该如何避免重复引入呢?

我们可以在模块中额外设置一个变量,使用if语句来检测这个变量是否存在,如果发现这个变量存在,就return出去。

这里需要强调一下return关键字。return在C++、C#、Java等大部分编程语言中只能退出函数,除此以外再无他用;但是在Shell中,return除了可以退出函数,还能退出由source命令引入的脚本文件。

所谓退出脚本文件,就是在被source引入的脚本文件(子文件)中,一旦遇到return关键字,后面的代码都不会再执行了,而是回到父脚本文件中继续执行source命令后面的代码。

return只能退出由source命令引入的脚本文件,对其它引入脚本的方式无效。

下面我们通过一个实例来演示如何避免脚本文件被重复引入。本例会涉及到两个脚本文件,分别是主文件main.sh和模块文件module.sh。

模块文件module.sh:

if[-n"$__MODULE_SH__"];thenreturnfi__MODULE_SH__='module.sh'echo"http://c.biancheng.net/shell/"

注意第一行代码,一定要是使用双引号把$__MODULE_SH__包围起来,具体原因已经在《Shelltest》一节中讲到。

主文件main.sh:

#!/bin/bashsourcemodule.shsourcemodule.shecho"hereexecuted"

./表示当前文件,你也可以直接写作sourcemodule.sh

运行main.sh,输出结果为:
http://c.biancheng.net/shell/
hereexecuted

我们在main.sh中两次引入module.sh,但是只执行了一次,说明第二次引入是无效的。

main.sh中的最后一条echo语句产生了输出结果,说明return只是退出了子文件,对父文件没有影响。