3.6. 函数、别名和环境

正如前面提到的,PS1、PS2、PS3、PS4 和 PROMPT_COMMAND 都存储在 Bash 环境中。对于我们这些来自 DOS 背景的人来说,将大块代码放入环境的想法令人恐惧,因为 DOS 环境很小,并且扩展性不好。 环境中可以和应该放入多少内容可能存在实际限制,但我不知道这些限制是什么,而且我们可能谈论的是比 DOS 用户习惯的量级大几个数量级。正如 Dan 所说

“在我的交互式 Shell 中,我有 62 个别名和 25 个函数。我的经验法则是,如果我需要一些仅用于交互式用途的东西,并且可以用 bash 轻松编写,我会将其设为一个 shell 函数(假设它不能轻易地表示为一个别名)。如果这些人担心内存,他们就不应该使用 bash。Bash 是我在我的 Linux 机器上运行的最大的程序之一(Oracle 除外)。 运行 top 命令,然后按 'M' 按内存排序 - 看看 bash 离列表顶部有多近。 见鬼,它比 sendmail 还大!告诉他们去用 ash 或其他的东西。”

我猜他尝试那天只使用了控制台:运行 X 和 X 应用程序,我有很多东西比 Bash 大。 但想法是一样的:环境是用来使用的,不用担心过度填充它。

我冒着被 Unix 大师们谴责的风险说这句话(因为过度简化),但函数基本上是为了效率而加载到环境中的小型 shell 脚本。再次引用 Dan 的话:“Shell 函数的效率可以达到最高。它大致相当于 source 一个 bash/bourne shell 脚本,只是因为函数已经存在于内存中,所以不需要进行文件 I/O。Shell 函数通常从 [.bashrc 或 .bash_profile] 加载,具体取决于你希望它们仅在初始 shell 中还是也在子 shell 中使用。 将此与运行 shell 脚本进行对比:你的 shell fork,子进程执行 exec,可能会搜索路径,内核打开文件并检查足够的字节以确定如何运行该文件,在 shell 脚本的情况下,必须使用脚本名称作为参数启动 shell,然后 shell 打开文件,读取它并执行语句。 与 shell 函数相比,除了执行语句之外的一切都可以被认为是多余的开销。”

别名很容易创建

alias d="ls --color=tty --classify"
alias v="d --format=long"
alias rm="rm -i"

你传递给别名的任何参数都会传递给别名命令的命令行(在前两种情况下是 ls)。请注意,别名可以嵌套,并且它们可以用来使普通的 unix 命令以不同的方式运行。(我同意不应该使用后一种别名的观点 - 如果你习惯于依赖 "rm *" 来询问你是否确定,你可能会在不使用你的别名的系统上丢失重要的文件。)

函数用于更复杂的程序结构。作为一般规则,对于任何可以用一行完成的事情,都使用别名。函数与 shell 脚本的不同之处在于,它们被加载到环境中,因此它们工作得更快。再次作为一般规则,你会希望保持函数相对较小,任何变得相对较大的 shell 脚本都应该保持为 shell 脚本,而不是将其转换为函数。你是否将某些内容加载为函数的决定也将取决于你使用它的频率。如果你不经常使用小型 shell 脚本,请将其保留为 shell 脚本。如果你经常使用它,请将其转换为函数。

为了修改...的行为ls,你可以做如下操作

function lf
{ 
    ls --color=tty --classify $*
    echo "$(ls -l $* | wc -l) files"
}

这可以很容易地设置为别名,但为了举例说明,我们将把它设为一个函数。如果将显示的文本输入到文本文件中,然后 source 该文件,该函数将位于你的环境中,并且可以立即在命令行中使用,而没有之前提到的 shell 脚本的开销。如果你考虑向上述函数添加更多功能,例如在使用 if 语句在列表中找到链接时执行一些特殊代码,那么它的用处将变得更加明显。