命令解释器成为编程语言
Bourne shell由斯蒂芬·伯恩在美国新泽西州默里希尔的贝尔实验室设计,是UNIX系统的命令解释器,也是一种用于组合命令的程序语言。它在1978年的《贝尔系统技术期刊》中得到系统介绍,随后成为1979年第七版UNIX所配备的新sh程序。交互输入与从文件执行的命令共享主要语法。
伯恩的设计继承肯·汤普森早期UNIX shell和程序员工作台PWB/UNIX shell的经验,并吸收更完整的控制结构。丹尼斯·里奇和约翰·马希参与了设计讨论。目标是在保持终端输入简洁的同时,让用户把经常重复的操作写成有参数、有条件分支和循环的命令过程。
把现有程序连成工作流程
一条简单命令由命令名和参数组成。shell查找程序、建立执行环境并等待它结束;命令末尾的与号可让程序在后台运行,用户继续输入其他操作。重定向则把通常连接终端的输入或输出改接文件,调用的程序仍按照标准输入、标准输出读写数据。
管道把前一程序的输出接到后一程序的输入。例如在普通文本日志中,grep error log | sort会选出含error的行,再按顺序排列;shell负责连接两个进程,grep和sort各自完成选择与排序。用户可以重新组合现有工具,而无需为每一种处理顺序编写新的专用程序。
参数使命令文件可以复用
命令既能逐行输入,也能存入文件,再以sh加文件名调用。脚本通过位置参数取得调用时提供的值:第一个参数由$1引用,$#给出参数个数。这样,同一个处理流程可以针对不同文件或查询词运行。具备执行属性的命令文件还能以类似普通程序的方式使用。
字符串变量保存名称、路径和选项,命令替换可以把一个命令的输出变成另一命令的输入参数。文件名模式由shell展开,例如星号用于匹配一组文件名。引号决定哪些字符保留原义、哪些继续替换,因此带空格的文件名和作为普通文字使用的通配符,需要相应的引用方式。
用退出状态决定下一步
Bourne shell把if、case、for和while等结构直接纳入解释器。条件判断依靠命令的退出状态,通常以零表示成功、非零表示失败;test命令可检查字符串、数字关系或文件属性。因此,流程控制与外部程序的运行结果能够在同一套命令语言中结合。
例如一个报表脚本可先判断输入文件是否存在,再执行排序;若文件不存在,就输出说明。for结构把同一操作依次应用到参数列表,case按模式选择不同分支。与单纯顺次执行命令相比,这些结构让脚本能够处理缺少参数、不同选项和操作失败等实际情况。
环境、登录配置与信号
用户通过搜索路径指定命令查找顺序,登录目录中的.profile保存进入会话时要执行的设置。变量可以被标记为export,使新启动的命令取得其值;子过程修改自己的变量,通常不会反向改变调用者。命令语言由此既组织操作步骤,也配置每一步运行时看到的环境。
对于需要随命令提供的一段文本,here document把输入数据直接放进脚本,减少额外文件的需求。trap则允许脚本在收到某些信号时执行收尾动作,例如处理临时文件后退出。这些设施扩展了命令过程的表达能力,也使输入、环境和异常退出成为程序结构的一部分。
第七版UNIX中的位置
第七版UNIX概要把新的sh与Fortran 77、文本处理、程序构建和系统可移植性改进一并列出,突出字符串变量、信号处理、结构化编程、用户配置和可设搜索路径。Bourne shell因此作为完整操作系统工具集的一部分传播,服务终端使用、程序开发和日常批处理。
伯恩的配套手册从简单命令讲到参数、控制流和高级用法,并给出由shell编写的实用命令过程。它展示了一种分工:独立程序完成具体计算或文本操作,shell负责选择、连接和调度这些程序。1979年第七版的意义在于把这种更完整的命令编程接口纳入系统分发,而其公开设计说明在上一年已经出现。