英语是一种令人困惑的语言。例如,请考虑 moon 和 good 这两个单词。对外行人而言,这两个单词似乎应该是押韵的,但是前者的读音是 /mun/(根据 International Pronunciation Alphabet),而后者的读音是 /good/。似乎英语中的惟一规则就是例外。
UNIX shell 同样令人困惑。例如,在 Bourne shell(和大多数常用的 UNIX shell)中,'$var'、"$var" 和 `$var` 看起来相似,但是它们会产生很不一样的结果。(在本文中的 shell 示例中,每个 CLI 前面都加上使用的 shell 的名称和命令编号) 。
获取 fish
fish 是由 Axel Liljencrantz 创建的一个开放源码项目,采用的许可协议是 GNU General Public License, version 2。到编写本文时,fish 的最新版本是 1.23.0,此版本于 2008 年 1 月 13 日发布。
如果使用 UNIX 或 UNIX 类系统(比如 Linux® 或 Mac OS X),那么应该很容易在您的系统上从源代码构建 fish。下面是构建步骤,见 清单 1:
下载程序的最新源代码压缩包。
解压。
进入源代码目录。
配置构建。
运行 make。
清单 1. 从源代码构建 fish
入门
在讨论比较复杂的主题之前,我们先看看在 fish 中如何完成一些常见的 shell 任务:
要想重定向标准输入和标准输出,应该分别使用操作符 < 和 >。要想重定向标准错误,应该使用 ^ 操作符,见 图 1。使用 ^^ 把标准错误追加到一个文件中。
图 1. 用 ^ 操作符重定向标准错误
在命令 3 中,rm 产生的错误消息被重定向到 errors 文件中。命令 4 显示此文件的内容。fish shell 为重定向提供各种支持,比如把描述符组合成一个流和结束描述符。
顺便说一句,文本的颜色和下划线不是编辑出来的。shell 会在您输入时在 CLI 中突出显示文本。绿色表示命令名是有效的;无效的命令名用红色表示。下划线表示指定的文件存在。(后面一节详细讨论 shell 的反馈)。
使用圆括号(())运行子 shell,见 图 2。圆括号中的文本被解释为一系列命令,shell 会把它们替换为执行结果。
图 2. 使用圆括号运行子 shell
通过创建 fish 函数创建别名(即快捷方式)。
函数可以包含一个或多个命令,特殊变量 $argv 会自动展开成命令行上传递的参数列表。
可以用 functions 命令列出已定义的所有函数。使用 functions --erase name 删除函数,例如 functions --erase ll。
还可以立即保存在命令行上编写的任何函数。在编写完代码时,输入 funcsave name,例如 funcsave ll。在此之后,当前运行的所有 shell 和以后的所有 shell 都可以使用此函数。可以使用 funced name 命令以交互方式编辑现有的函数。funced 命令提供语法突出显示、制表符补全和自动缩进;funcsave 和 funced 使用户能够更方便地定制 shell。
输入 set variable namevalue 来设置变量。与内置命令 functions 一样,输入 set --erase variable name 就可以删除一个变量。输入美元符号($)和变量名,就可以获取变量中存储的值,见 图 3。
图 3. 检查一个变量是否存在
fish 提供 --query 选项来检查是否定义了一个变量。如果已经设置了此变量,set --query 返回状态码 0,这表示没有出现错误;否则,返回 1。语句 6 用 or 操作符连接两个命令:第二个命令(echo)只在第一个命令失败的情况下执行。
那么,fish 如何处理 $var、'$var'、"$var" 和 `$var` 呢?它遵守几条简单的规则:
如果变量包含空格,那么空格会被保留,变量总是作为单一参数,见 图 4。
图 4. fish 按原样保留字符串中嵌入的空格
如果最外边的引号是双引号,那么展开所有变量。
如果最外边的引号是单引号,那么不展开变量。
我们来看看这些规则的实际应用。
命令 1 创建四个 文件,最后一个文件的名称包含空格。命令 3 和 4 删除 file 变量指定的文件。命令 6 和 7 删除 twofiles 变量指定的两个文件。仔细看一下命令 6:因为值没有放在引号(单引号或双引号)中,所以不保留空格。因此,命令 7 把此变量展开成两个参数并删除两个文件。命令 9 和 10 重复命令 6 和 7 中的场景。
命令 11 和 12 演示空格规则。尽管在命令 12 中变量没有放在双引号中,但是 fish 在命令 11 中保留空格。非常好。
命令 14 到 16 演示 fish 的嵌套引号规则。现在,再看一下命令 11、15 和 16。shell 使用颜色编码显示匹配的引号,以此确保语法正确。再看一下命令 9 和 11。后一个命令在文件名上显示下划线,这表示此文件存在。在命令 9 中没有下划线,这提示用户某些地方出错了。
fish 的首字母代表 Friendly,对用户友好是它的主要目标。
对于新手非常有帮助的一个特性
说到对用户友好,就不能不提到 fish 的制表符补全 特性,这个新颖的特性对于 UNIX 新用户和专家都极其有帮助。为了体验制表符补全,请按下面的示例操作。在每行的末尾按 Tab 键。
如果您不确定一个命令名的拼写,可以在输入几个字母之后按 Tab,就会看到可能的完整命令的列表,见 图 5。(在您的系统上显示的命令列表可能与这里显示的不一样。此列表取决于 PATH 环境变量和您的 UNIX 系统的内容) 。
图 5. 按 Tab 补全命令名
注意 CLI 中的红色文本。如果 fish 不认识一个命令名,就用红色显示它。按 Tab,就会显示以目前输入的字母开头的所有应用程序名(以及简短的描述)。在空提示行上按 Tab,就会看到 PATH 中的所有应用程序。
如果想了解一个命令的可用选项,那么在连字符(-)或双连字符(--)后面按 Tab,见 图 6。
图 6. 还可以通过按 Tab 补全一个选项
此时,fish 会显示可用的选项。shell 维护许多常用命令和选项的索引,您很可能能够得到所需的帮助。但是,定制的或更复杂的实用程序可能缺少这种数据。可以阅读 fish 文档,了解关于编写自己的补全特性的更多信息。
还可以在输入选项的几个字母之后按 Tab,见 图 7。shell 会显示所有匹配的选项。
图 7. 还可以输入选项的一部分
如果您不知道一个命令处理的操作数类型,fish 在许多情况下可以提供帮助,但并不是在所有情况下都可以。例如,如果输入 set(或 vared,即 fish 变量编辑器)和一个空格,然后按 Tab,fish 会显示可用变量的列表。set 的操作数是一个变量。同样,如果输入 type 和一个空格,然后按 Tab,fish 会显示内置函数的列表,这些函数扩展文件系统上可用的实用程序。
在一般情况下,fish 中的所有内置函数都有上下文相关的操作数补全。请试一下 cd,见 图 8。
图 8. 许多命令是上下文相关的,可以显示适当的参数
cd 函数是一个 fish 函数,它的操作数是一个现有的目录。在输入 cd 之后按 Tab,fish 会显示 CDPATH 中的每个目录包含的所有现有目录。
另一个智能化补全与 ssh 相关。输入 ssh 和一个空格,然后按 Tab,就会看到从 Secure Shell 已知主机文件(通常在 ~/.ssh/known_hosts 中)获取的已知主机名列表:、
使用 fish 作为登录 shell
如果您喜欢 fish,希望用它作为登录 shell,那么把 fish 的路径添加到正式 shell 列表(/etc/shells)中,然后运行 chsh:
结束语
fish 中还有许多有用的特性值得研究。“fish 这条鱼非常有营养。”
可以调整语法突出显示采用的颜色。可以通过编辑 ~/.config/fish/config.fish 定制启动过程。可以使用通用变量 和 fishd 跨 shell 实例共享变量。这种 shell 还有出色的历史搜索特性、交互式变量编辑器和交互式命令行编辑器。
最好的一点是,fish 本身提供大量文档。如果需要帮助,只需在命令提示上输入 help。
医生的意见是对的:吃 “鱼” 对您有益。
新闻热点
疑难解答