1.4.1. Shell 构建

1.4.1.1. Shell 语法

如果输入没有注释,shell 会读取它并将其分成单词和运算符,使用引用规则来定义输入的每个字符的含义。然后这些词和操作符被翻译成命令和其他结构,用于检查或处理退出状态。上述 fork-and-exec 方案仅在 shell 以下列方式分析输入后:

  • shell 从文件、字符串或用户终端读取其输入。
  • 输入被分解成单词和操作符,遵守引用规则,见第 3 章。这些标记由元字符分隔。执行别名扩展。
  • shell 解析 (分析和替换) 单词为简单或组合命令
  • Bash 执行各种 shell 扩展,将扩展的语句分解为文件名、命令和参数列表。
  • 必要时会执行重定向,重定向运算符及其操作数会从参数列表中删除。
  • 命令被执行.
  • shell 可选等待命令完成并收集其退出状态。

1.4.1.2. Shell commands

一个简单的 shell 命令,例如touch file1 file2 file3由命令本身和后面的参数组成,用空格分隔。

更复杂的 shell 命令由以多种方式排列在一起的简单命令组成:在管道中,一个命令的输出成为第二个命令的输入,比如在循环或条件构造中,或在其他一些分组中。几个例子:

ls | more

gunzip file.tar.gz | tar xvf -

1.4.1.3. Shell functions

Shell 函数是一种使用单个名称对命令分组并供以后执行的方法。它们就像“常规”命令一样执行。当 shell 函数的名称用作简单命令名称时,将执行与该函数名称关联的命令列表。

Shell 函数在当前 shell 上下文中执行;没有创建新的过程来解释它们。

1.4.1.4. Shell parameters

参数是存储值的实体。它可以是名称、数字或特殊值。对于 shell 而言,变量是存储名称的参数。一个变量有一个值和零个或多个属性。变量是使用declare 命令创建的。

如果没有给出值,则为变量分配null字符串。只能使用内置的unset删除变量。

1.4.1.5. Shell expansions

在将每个命令行拆分为单词之后执行 Shell 扩展。这些是执行的扩展:

  • 大括号 Brace expansion
  • 波浪号 Tilde expansion
  • 参数和变量 Parameter and variable expansion
  • 命令替换
  • 算术Arithmetic expansion
  • 切分单词Word splitting
  • Filename expansion

1.4.1.6. 重定向

在执行命令之前,可以使用 shell 的特殊符号重定向其输入和输出。重定向也可用于打开和关闭当前 shell 执行环境的文件。

1.4.1.7. 执行命令

执行命令时,解析器标记单词为其变量分配(在命令名称之前)并且保存重定向供以后使用。不是变量赋值或重定向的单词会被扩展;扩展后的第一个剩余单词被视为命令的名称,其余的都是该命令的参数。然后执行重定向,然后扩展分配给变量。如果找不到命令名,变量将影响当前的 shell 环境。

shell 任务的一个重要部分是搜索命令。Bash 这样做如下:

  • 检查命令是否包含斜杠。如果没有,首先检查函数列表,看看它是否包含我们正在寻找的名称的命令。
  • 如果 command 不是函数,请在内置命令列表中检查它。
  • 如果 command 既不是函数也不是内置函数,在PATH 中列出的目录里查找。Bash 使用哈希表(内存中的数据存储区域)来记住可执行文件的完整路径名,避免大量的PATH搜索。
  • 如果搜索不成功,bash 会打印一条错误消息并返回退出状态 127。
  • 如果搜索成功或命令包含斜杠,shell 将在单独的执行环境中执行命令。
  • 如果由于文件不可执行且不是目录而导致执行失败,则假定它是一个 shell 脚本。
  • 如果命令不是异步的,shell 会等待命令完成并收集其退出状态。

1.4.1.8. Shell scripts

当一个包含 shell 命令的文件被用作调用 Bash 时的第一个非选项参数时(没有-c或-s,这将创建一个非交互式 shell)。这个 shell 首先在当前目录中搜索脚本文件,然后查找不到,则在PATH 中查找。