├── .github └── workflows │ └── main.yml ├── .gitignore ├── LICENSE ├── README.md ├── content ├── 00-translator-notes.md ├── 01-manual-description.md ├── 02-introduction.md ├── 03-roadmap.md ├── 04-invocation.md ├── 05-files.md ├── 06-shell-grammer.md ├── 07-redirection.md ├── 08-command-execution.md ├── 09-functions.md ├── 10-jobs-and-signals.md ├── 11-atithmetics.md ├── 12-conditionals.md ├── 13-prompt-expns.md ├── 14-expansions.md ├── 15-parameters.md ├── 16-options.md ├── 17-builtins.md ├── 18-zle-line-editor.md ├── 19-completion-widgets.md ├── 20-completion-system.md ├── 21-compctl-completions.md ├── 22-zsh-modules.md ├── 23-zcal-calendar.md ├── 24-ztcp-tcpsocket.md ├── 25-zftp-ftpclient.md ├── 26-user-contrib.md ├── index.md └── stylesheets │ └── extra.css ├── mkdocs.yml └── requirements.txt /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | deploy: 10 | runs-on: ubuntu-latest 11 | steps: 12 | - name: Checkout 13 | uses: actions/checkout@v2 14 | - name: Setup Python 15 | uses: actions/setup-python@v4 16 | with: 17 | python-version: '3.10' 18 | - name: Install dependencies 19 | run: | 20 | python -m pip install --upgrade pip 21 | pip install -r requirements.txt 22 | - name: Check dependencies 23 | run: | 24 | mkdocs --version 25 | - name: Build 26 | run: | 27 | mkdocs build 28 | - name: Deploy 29 | uses: peaceiris/actions-gh-pages@v3 30 | with: 31 | github_token: ${{ secrets.GITHUB_TOKEN }} 32 | publish_dir: ./site 33 | publish_branch: gh-pages 34 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Translations 2 | *.mo 3 | *.pot 4 | 5 | # Scrapy stuff: 6 | .scrapy 7 | 8 | # pyenv 9 | .python-version 10 | 11 | # pipenv 12 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 13 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 14 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 15 | # install all needed dependencies. 16 | #Pipfile.lock 17 | 18 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 19 | __pypackages__/ 20 | 21 | # SageMath parsed files 22 | *.sage.py 23 | 24 | # Environments 25 | .env 26 | .venv 27 | env/ 28 | venv/ 29 | ENV/ 30 | env.bak/ 31 | venv.bak/ 32 | 33 | # mkdocs documentation 34 | /site 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | (C) Paul Falstad 2 | (C) 2020-2022 夜坂雅及其他贡献者 (Translation) 3 | 4 | Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. 5 | 6 | Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. 7 | 8 | Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ShadowRZ/zshdocs-zh 2 | 3 | Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. 4 | 5 | Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. 6 | 7 | Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. 8 | 9 | ## 进度 10 | 11 | - [x] 1 The Z Shell Manual 12 | - [x] 2 Introduction 13 | - [x] 3 Roadmap 14 | - [x] 4 Invocation 15 | - [x] 5 Files 16 | - [ ] 6 Shell Grammar 17 | - [ ] 7 Redirection 18 | - [ ] 8 Command Execution 19 | - [ ] 9 Functions 20 | - [ ] 10 Jobs & Signals 21 | - [ ] 11 Arithmetic Evaluation 22 | - [ ] 12 Conditional Expressions 23 | - [ ] 13 Prompt Expansion 24 | - [ ] 14 Expansion 25 | - [ ] 15 Parameters 26 | - [ ] 16 Options 27 | - [ ] 17 Shell Builtin Commands 28 | - [ ] 18 Zsh Line Editor 29 | - [ ] 19 Completion Widgets 30 | - [ ] 20 Completion System 31 | - [ ] 21 Completion Using compctl 32 | - [ ] 22 Zsh Modules 33 | - [ ] 23 Calendar Function System 34 | - [ ] 24 TCP Function System 35 | - [ ] 25 Zftp Function System 36 | - [ ] 26 User Contributions 37 | 38 | ## Project layout 39 | 40 | mkdocs.yml # The configuration file. 41 | content/ 42 | index.md # The documentation homepage. 43 | ... # Other markdown pages, images and other files. 44 | -------------------------------------------------------------------------------- /content/00-translator-notes.md: -------------------------------------------------------------------------------- 1 | # 译者注释 2 | 3 | %% 表示对尚未翻译的章节的引用。 4 | 5 | {>>译注:这种文字表示译者的附注。<<} 6 | -------------------------------------------------------------------------------- /content/01-manual-description.md: -------------------------------------------------------------------------------- 1 | # 第一章:Zsh 手册 2 | 3 | !!! note "译者注释" 4 | 这部分内容是描述如何生成 Zsh 原文档的,因此不适用于翻译版。 5 | 6 | 本文档是通过 Zsh 发行中,`Doc` 子目录里的 `zsh.texi` 生成的。 7 | 8 | ## 从 zsh.texi 中生成文档 9 | 10 | Texinfo 源可转为以下格式: 11 | 12 | Info 手册 13 | : Info 格式允许从诸多索引中搜索话题、命令、函数等。用 `makeinfo zsh.texi` 生成 Info 文档。 14 | 15 | 打印手册 16 | : `texi2dvi zsh.dvi` 命令会生成 `zsh.dvi`,它可以用 _dvips_ 和可选的 _gs_ (Ghostscript) 生成格式较好的手册。 17 | 18 | HTML 手册 19 | : HTML 手册可通过以下位置在 Zsh 网站上找到: 20 | [http://zsh.sourceforge.net/Doc/](http://zsh.sourceforge.net/Doc/). 21 | (HTML 版使用 _text2html_ 生成,它可从 http://www.nongnu.org/texi2html/ 获取。命令是:`texi2html –output . –ifinfo –split=chapter –node-files zsh.texi`。如有必要,升级到 1.78 版本的 text2html。) 22 | 23 | 对于那些没有必要工具处理 Texinfo 的人们,预编译文档(Postscript,DVI,PDF 和 HTML 格式)可从 Zsh 归档站或其镜像获取。在文件 `zsh-doc.tar.gz` 中。(站点列表见 [-> 获取](02-introduction.md#_3)) 24 | {>>译注:我们呢?<<} 25 | -------------------------------------------------------------------------------- /content/02-introduction.md: -------------------------------------------------------------------------------- 1 | # 第二章:简介 2 | 3 | Zsh 是一个 UNIX 命令解释器(Shell),可用于交互登录 Shell 以及作为 Shell 脚本指令处理器。在标准 Shell 中,Zsh 最接近于 _ksh_ 但附带了许多改进。在默认工作模式下它不提供与 POSIX 或其他 Shell 的兼容性:见章节 %%。 4 | 5 | Zsh 包括了命令行编辑,内建拼写纠正,可编程命令补全,Shell 函数(包括自装入机制),历史系统,以及其他诸多功能。 6 | 7 | ## 作者 8 | 9 | Zsh 最初由 Paul Falstad `` 编写。Zsh 现由 zsh-workers 邮件列表 `` 的成员维护。其开发现由 Peter Stephenson `` 协调。协调者可通过 `` 联系。但关于代码的事通常应该跑到邮件列表。 10 | 11 | ## 获取 12 | 13 | Zsh 可从以下 HTTP 和匿名 FTP 站下载。 14 | 15 | ftp://ftp.zsh.org/pub/ 16 | https://www.zsh.org/pub/ 17 | 18 | 最新源码可通过 Sourceforge Git 获取。详情见 [https://sourceforge.net/projects/zsh/](https://sourceforge.net/projects/zsh/)。对此归档的操作概要可在 http://zsh.sourceforge.net/ 找到。 19 | 20 | ## 邮件列表 21 | 22 | Zsh 有三个邮件列表: 23 | 24 | `` 25 | : 发行宣告,Shell 大变更以及月更的 Zsh FAQ。(审核) 26 | 27 | `` 28 | : 用户讨论。 29 | 30 | `` 31 | : 调教,开发,Bug 报告和补丁。 32 | 33 | 如要订阅或退订,向邮件列表相应的管理地址发邮件。 34 | 35 | `` 36 | `` 37 | `` 38 | `` 39 | `` 40 | `` 41 | `` 42 | 43 | **你只需要加入其中一个邮件列表,因为他们是嵌套的。**_zsh-announce_ 全部发件会自动转发到 _zsh-users_。_zsh-users_ 全部发件会自动转发到 _zsh-workers_。 44 | 45 | 如你订阅/退订时遇到任何问题,向 `` 发邮件。邮件列表由 Karsten Thygesen `` 维护。 46 | 47 | 邮件列表是归档的。归档可通过上方列出的管理地址访问。另有 Geoff Wing `` 维护的超文本归档,可在 https://www.zsh.org/mla/ 访问。 48 | 49 | ## Zsh FAQ 50 | 51 | Zsh 有一份由 Peter Stephenson `` 常见问题列表(FAQ)。它经常被发到 _comp.unix.shell_ 和 _zsh-announce_ 邮件列表。最新版可在任何 Zsh FTP 站或 http://www.zsh.org/FAQ/ 找到。与 FAQ 有关的事务的联系地址是 ``。 52 | 53 | ## Zsh 网页 54 | 55 | Zsh 有一个在 https://www.zsh.org/ 的网页。它由 SunSITE Denmark 的 Karsten Thygesen `` 维护。与网页有关的事务的联系地址是 ``。 56 | 57 | ## Zsh 用户手册 58 | 59 | 用户手册正处于准备阶段。它主要用于手册的补充,包括对手册中神秘的部分的解说和提示。可在 http://zsh.sourceforge.net/Guide/ 以现状查看。编写此文档时,与启动文件有关的章节和内容,以及新补全系统部分已基本完成。 60 | 61 | ## 另见 62 | 63 | 手册页 `sh(1)`,手册页 `csh(1)`,手册页 `tcsh(1)`,手册页 `rc(1)`,手册页 [`bash(1)`](https://tiswww.case.edu/php/chet/bash/bash.html),手册页 `ksh(1)` 64 | -------------------------------------------------------------------------------- /content/03-roadmap.md: -------------------------------------------------------------------------------- 1 | # 第三章:路程图 2 | 3 | Zsh 手册,就像 Shell 本身一样大,且常常很复杂。本章指出一些新用户可能很感兴趣的 Shell 机能,并指出应该到哪里找到其文档。 4 | 5 | ## 当 Shell 启动 6 | 7 | 当它启动时,Shell 从各种文件中读取指令。可以通过创建及编辑它们自定义 Shell。详见 %%。 8 | 9 | 如当前用户没有个人的载入文件,会运行一个函数帮你更改一些最常见设置。如果你的管理员关闭了 `zsh/newuser` 模块它将不会出现。你可以用 `autoload -Uz zsh-newuser-install; zsh-newuser-install -f` 手动运行。另见 %%。 10 | 11 | ## 交互使用 12 | 13 | 与 Shell 的交互使用内建 Zsh 行编辑器,ZLE。将在 %% 中详细介绍。 14 | 15 | 用户的第一个抉择是要使用 Emacs 或 Vi 编辑模式,因为编辑的按键全然不同。Emacs 编辑模式可能对萌新更自然,可以通过 `bindkey -e` 显式选择。 16 | 17 | 你可以使用一个取回以前输入过的行(通常通过简单的 ++up++ 或 ++down++ 键)的历史系统;注意不像其他 Shell 的是,Zsh 不会在 Shell 退出时保存这些行,除非你设定相应变量,而且默认存储的历史行数很小(30 行)。详见 %% 中对 Shell 变量(文档中称其为参数)`HISTFILE`,`HISTSIZE` 和 `SAVEHIST` 的描述。注意目前只有 Shell 是交互状态时才能读写保存历史的文件,即它不能在脚本里工作。 18 | 19 | Shell 现在支持 UTF-8 字符集(以及其他操作系统支持的字符集)。(多数时候)Shell 透明处理他们,但终端支持度参差不齐。[Shell FAQ](https://www.zsh.org/FAQ/) 有相关讨论。尤其需要注意的是需设置 `COMBINING_CHARS` 选项,组合字符才会被支持。因为 Shell 现对字符集定义更敏感,所以要注意如果你从旧版升级的时候,你要确保一些相应的变量,要么是 `LANG`(影响所有 Shell 操作要素)或 `LC_CTYPE`(只影响字符集处理)被设为合适的值。即使你使用包括了 ASCII 扩展的单字节字符集,如 `ISO-8859-1` 或 `ISO-8859-15` 也同样适用。详见 %% 中 `LC_CTYPE` 的描述。 20 | 21 | ### 补全 22 | 23 | 补全是诸多 Shell 拥有的功能。它允许用户只打一部分(通常是前缀)词并让 Shell 填充剩下的部分。Zsh 的补全系统是可编程的。例如,Shell 可配置为从你的 `~/.abook/addressbook` 中补全参数的邮件地址;scp 中的用户名,主机名,甚至远端路径参数,等等。任何能用 Zsh 编写或粘合的东西都可以被用于行编辑器提供的可能的补全。 24 | 25 | Zsh 有两个补全系统,一个是古老的,被称作 `compctl` 补全系统(因一个作为完整且唯一的用户界面的内建命令而得名),以及分成一个内建库和用户函数,被称作 `compsys` 的补全系统。二者区别在于指定补全行为的接口。新系统更可定制,并提供了许多常用命令的补全;因此被推荐使用。 26 | 27 | Shell 启动时必须显式启用补全系统。更多信息见 %%。 28 | 29 | ### 扩展行编辑器 30 | 31 | 除了补全,行编辑器可通过 Shell 函数高度扩展。Shell 提供了一些有用的函数:它们提供诸如以下的机能: 32 | 33 | `insert-composed-char` 34 | : 输入不在键盘上的组合字符 35 | 36 | `match-words-by-style` 37 | : 配置行编辑器在移动或删除一个词时把什么当作一个词 38 | 39 | `history-beginning-search-backward-end` 等 40 | : 搜索 Shell 历史的其他方式 41 | 42 | `replace-string`, `replace-pattern` 43 | : 命令行里全局替换字符串或模式的函数 44 | 45 | `edit-command-line` 46 | : 用外部编辑器编辑命令行 47 | 48 | 其描述详见 %%。 49 | 50 | ## 选项 51 | 52 | Shell 有大量选项用于改变其行为。其覆盖了所有 Shell 要素;浏览完整文档是掌握许多可能的唯一合适方法。见 %%。 53 | 54 | ## 模式匹配 55 | 56 | Shell 有诸多用于文件名匹配(文档中称其为“文件名生成 (filename generation),亦因历史原因常被叫做 “globbing”)和用于编程的丰富模式。这在 %% 中有详细介绍。 57 | 58 | 尤其令人感兴趣的是以下其他模式匹配系统不常支持的模式: 59 | 60 | `**` 61 | : 匹配多个目录 62 | 63 | `|` 64 | : 匹配二者中任一 65 | 66 | `~`, `^` 67 | : 设置 `EXTENDED_GLOB` 时在匹配中排除某个模式 68 | 69 | `(...)` 70 | : Glob 界定符,置于模式尾部并被放在括号之内,可以按类型(如目录)或属性(如大小)选择文件。 71 | 72 | ## 语法注解 73 | 74 | 尽管 Zsh 的语法与 Korn Shell 有相似之处,并连带相似于原始 UNIX Shell Bourne Shell,然而其默认行为并不与这些 Shell 完全对应。一般 Shell 语法在 %% 介绍。 75 | 76 | 一个常见的不同点是替换到命令的变量不会被按词分割。详见 %% 中 `SH_WORD_SPLIT` 的描述。Zsh 中你既可以显式要求分割(如 `${=foo}`)或当你想把一个变量展开成多于一个词时使用数组。见 %%。 77 | 78 | ## 编程 79 | 80 | 向 Shell 添加改进最便捷的方法通常是编写个 Shell 函数并组织它自装入。函数在 %% 中介绍。从 C Shell 及其相似 Shell 的用户赢注意别名在 Zsh 中更少使用,因为其不执行参数代换,只有简单文字替换。 81 | 82 | Shell 还提供除上面提到的用于行编辑器的函数的一些通用函数,在 %% 中有描述。包括以下机能: 83 | 84 | `promptinit` 85 | : 简单更改提示符的提示符主题系统。见 %% 86 | 87 | `zsh-mime-setup` 88 | : 按照文件后缀分配命令的 MIME 处理系统,就像图形文件管理器做的那样 {>>译注:file(1):喵喵喵?<<} 89 | 90 | `zcalc` 91 | : 计算器 92 | 93 | `zargs` 94 | : 可以让 `find` 命令退职的一个 `xargs` 版本 95 | 96 | `zmv` 97 | : 用 Shell 模式重命名文件的指令。 98 | -------------------------------------------------------------------------------- /content/04-invocation.md: -------------------------------------------------------------------------------- 1 | # 第四章:启动 2 | 3 | ## 启动 4 | 5 | Shell 被执行时会识别以下参数确定 Shell 从哪里读取指令: 6 | 7 | `-c` 8 | : 取第一个参数作为执行的命令,而非从脚本或标准输入读取命令。若其后给了任何参数,第一个被赋值 `$0`,而非作为位置参数使用。 9 | 10 | `-i` 11 | : 强制交互 Shell,仍可以指定执行的脚本。 12 | 13 | `-s` 14 | : 强制 Shell 从标准输入读取命令。若未给 `-s` 参数且传入一个参数,第一参数作为要执行的脚本的路径。 15 | 16 | 若选项处理后仍有剩余参数,且 `-c` 和 `-s` 都未指定,第一参数作为包含 Shell 命令的脚本文件名。如设置选项 `PATH_SCRIPT`,且文件名不含目录路径(即名字中没有 `/`),先按当前目录后按变量 `PATH` 中指定的命令路径搜索脚本。如未设该选项或名字中包含 `/` 它会被直接使用。 17 | 18 | 在按上述内容处理前一两个参数后,余下的参数即作为位置参数。 19 | 20 | 更多常见于启动与内建命令 `set` 的选项,详见 [-> 选项](16-options.md) 21 | 22 | 可向 Shell 传递长选项 `--emulate` 及(以一个单独的词形式)尾随其后的一个模拟模式。模拟模式是 `emulate` 中描述的模式,详见 [-> Shell 内建命令](17-builtins.md)。`--emulate` 选项必须置于其他(可能被覆盖的)选项之前,所以可用于改变要求的模拟模式。注意相较于 Shell 内的 `emulate` 命令,使用此选项后会为平滑模拟做出额外步骤:例如 Shell 内像 `path` 这样与 POSIX 用法相违背的变量不会被定义。 23 | 24 | 选项可以用 `-o` 选项按名字指定。`-o` 像一个单字符选项,但取下一个字符串作为选项名。例如: 25 | 26 | ```zsh 27 | zsh -x -o shwordsplit scr 28 | ``` 29 | 30 | 运行脚本 `scr`,通过相应字符 `-x` 设置 `XTRACE` 选项并通过名字设置 `SH_WORD_SPLIT` 选项。可使用 `+o` 而非 `-o` _关闭_ 选项。`-o` 可以与前置的单字符选项堆叠在一起,所以举例 `-xo shwordsplit` 或 `-xoshwordsplit` 等效于 `-x -o shwordsplit`。 31 | 32 | 选项也可以通过 GNU 长选项风格 `--option-name` 按名字指定。这么做时,选项名中允许有 `-`:它们被转换成 `_`,因此被忽略。所以举例,`zsh --sh-word-split` 执行 Zsh 并启用 `SH_WORD_SPLIT` 选项。像其他选项语法一样,可以通过把首个 `-` 换成 `+` 来关闭选项;因此 `+-sh-word-split` 等效于 `--no-sh-word-split`。不像其他选项格式,GNU 式长选项不可以和其他任何选项堆在一起。因此举例 `-x-shwordsplit` 是个错误,而非像 `-x --shwordsplit` 那样处理。 33 | 34 | 特殊的 GNU 式选项 `--version` 也会被处理;它会向标准输出输出 Shell 版本信息,然后成功退出。`--help` 也会被处理;它会向标准输出输出当执行 Shell 时可用的选项。然后成功退出。 35 | 36 | 选项处理可以以两种方式结束,允许随后以 `-` 或 `+` 开头的参数作为普通参数使用。首先,单独的 `-`(或 `+`)本身作为参数使用会结束选项处理。其次是特殊选项 `--`(或 `+-`),可以单独使用(这是标准 POSIX 用法)或前置堆叠选项(所以 `-x-` 与 `-x --` 等效)`--` 后不允许堆叠选项(所以 `-x-f` 是个错误),但注意上文提及的 GNU 式选项,此时允许 `--shwordsplit` 而不结束选项处理。 37 | 38 | 除非 _sh_/_ksh_ 模拟的单字符选项有效,`-b`(或 `+b`)结束选项处理。`-b` 类似于 `--`,除了更多的单字符选项可以堆叠在 `-b` 之后且会正常产生效果。 39 | 40 | ## 兼容性 41 | 42 | 当 Zsh 被以 `sh` 或 `ksh` 运行时,会相应模拟 _sh_ 或 _ksh_;更准确说,它首先查看它被启动时的名字里的第一个字符,除去任何开头的 `r`(假定表示“限制 Shell”),如果是 `b`,`s` 或 `k` 会模拟 _sh_ 或 _ksh_。并且,若以 `su` 执行(某些系统当 Shell 被 su 执行时会这样),Shell 会试图从 `SHELL` 环境变量中取备选名字并基于此执行模拟。 43 | 44 | 在 _sh_ 和 _ksh_ 兼容模式下以下参数失去特殊性且 Shell 不载入:`ARGC`,`argv`,`cdpath`,`fignore`,`fpath`,`HISTCHARS`,`mailpath`,`MANPATH`,`manpath`,`path`,`prompt`,`PROMPT`,`PROMPT2`,`PROMPT3`,`PROMPT4`,`psvar`,`status`,`watch`。 45 | 46 | 通常的 Zsh 启动/退出脚本不会被执行。登录 Shell 读取 `/etc/profile` 而后是 `$HOME/.profile`。若执行时设置 `ENV` 环境变量,读取登录脚本后读取 `$ENV`。`ENV` 的值会在解析为路径名时受到参数展开,命令替换,和算术展开。注意 `PRIVILEGED` 选项也会影响启动文件的执行。 47 | 48 | 若 Shell 以 `sh` 或 `ksh` 执行,以下选项会被设置:`NO_BAD_PATTERN`,`NO_BANG_HIST`,`O_BG_NICE`,`NO_EQUALS`,`NO_FUNCTION_ARGZERO`,`GLOB_SUBST`,`NO_GLOBAL_EXPORT`,`NO_HUP`,`INTERACTIVE_COMMENTS`,`KSH_ARRAYS`,`NO_MULTIOS`,`NO_NOMATCH`,`NO_NOTIFY`,`POSIX_BUILTINS`,`NO_PROMPT_PERCENT`,`RM_STAR_SILENT`,`SH_FILE_EXPANSION`,`SH_GLOB`,`SH_OPTION_LETTERS`,`SH_WORD_SPLIT`。同时若 Zsh 以 `sh` 执行还会设置选项 `BSD_ECHO` 和 `IGNORE_BRACES`。同时若 Zsh 以 `ksh` 执行会设置选项 `KSH_OPTION_PRINT`,`LOCAL_OPTIONS`,`PROMPT_BANG`,`PROMPT_SUBST` 和 `SINGLE_LINE_ZLE`。 49 | 50 | ## 限制 Shell 51 | 52 | 当 Zsh 以 `r` 开头的命令基础名执行或启动时指定 `-r`,Shell 会变成限制 Shell。模拟模式在去掉启动名前的 `r` 之后确定。限制模式中禁用以下事项: 53 | 54 | - 用 `cd` 内建命令更改目录 55 | - 改变或取消设置参数 `EGID`,`EUID`,`GID`,`HISTFILE`,`HISTSIZE`,`IFS`,`LD_AOUT_LIBRARY_PATH`,`LD_AOUT_PRELOAD`,`LD_LIBRARY_PATH`,`LD_PRELOAD`,`MODULE_PATH`,`module_path`,`PATH`,`path`,`SHELL`,`UID` 和 `USERNAME`。 56 | - 指定带 `/` 的指令名 57 | - 用 `hash` 指定命令路径名 58 | - 重定向输出到文件 59 | - 用 `exec` 内建命令把 Shell 替换为其他命令 60 | - 用 `jobs -Z` 改写 Shell 进程的参数和环境空间 61 | - 用 `ARGV0` 参数覆盖外部指令的 `argv[0]` 62 | - 用 `set +r` 或 `unsetopt RESTRICTED` 关闭限制模式 63 | 64 | 这些限制在处理完启动文件后被强制应用。启动文件应该把 `PATH` 指向含有能安全在限制环境里运行的命令的目录。也可以通过关闭内建命令添加更多限制。 65 | 66 | 限制模式也可以在任何时候通过设置 `RESTRICTED` 选项启动。这会导致以上限制被立即应用,即使 Shell 仍未处理完启动文件。 67 | -------------------------------------------------------------------------------- /content/05-files.md: -------------------------------------------------------------------------------- 1 | # 第五章:文件 2 | 3 | ## 启动 / 退出文件 4 | 5 | 命令会首先从 `/etc/zshenv` 读取,这一点不可以被覆盖。随后的行为会被选项 `RCS` 和 `GLOBAL_RCS` 修改;前者影响所有启动文件,后者只影响全局启动文件(即此处所述文件中以 `/` 开头的文件)。若任意时刻取消设定其中一个选项,任何对应类型的启动文件随后都不会被读取。`$ZDOTDIR` 中的一个文件重新启用 `$GLOBAL_RCS` 亦可。`RCS` 及 `GLOBAL_RCS` 默认都被设定。 6 | 7 | 随后命令会从 `$ZDOTDIR/.zshenv` 读取,若 Shell 是登录 Shell,命令会先后从 `/etc/zprofile` 及 `$ZDOTDIR/.zprofile` 读取。然后若 Shell 是交互的,命令会先后从 `/etc/zshrc` 及 `$ZDOTDIR/.zshrc` 读取。最后如果 Shell 是登录 Shell,读取 `/etc/zlogin` 和 `$ZDOTDIR/.zlogin`。 8 | 9 | 登录 Shell 退出的时候,会读取 `$ZDOTDIR/.zlogout` 和 `/etc/zlogout`。这会在通过 `exit` 或 `logout` 命令显式退出或者终端读取文件末尾标识符的隐式退出。然而若 Shell 因 `exec` 到其他程序退出,将不会读取登出文件。这也会受选项 `RCS` 和 `GLOBAL_RCS` 的影响。注意 `RCS` 选项影响历史文件的保存,即若 Shell 退出时未设定 `RCS`,就不会保存历史文件。 10 | 11 | 若 `ZDOTDIR` 未设定,会使用 `HOME` 代替。取决于安装,上述位于 `/etc` 的文件也可能在另一目录。 12 | 13 | 由于 `/etc/zshenv` 会被所有 Zsh 实例运行,保持它尽可能小很重要,把不需要每个 Shell 都运行的代码置于形如 `if [[ -o rcs ]]; then ...` 的测试代码后也是好主意,这样 Zsh 带 `-f` 选项启动时就不会执行它们。 14 | 15 | ## 文件列表 16 | 17 | `$ZDOTDIR/.zshenv` 18 | `$ZDOTDIR/.zprofile` 19 | `$ZDOTDIR/.zshrc` 20 | `$ZDOTDIR/.zlogin` 21 | `$ZDOTDIR/.zlogout` 22 | `${TMPPREFIX}*` (默认 /tmp/zsh*) 23 | `/etc/zshenv` 24 | `/etc/zprofile` 25 | `/etc/zshrc` 26 | `/etc/zlogin` 27 | `/etc/zlogout`(取决于安装 - 默认 `/etc/`) 28 | 29 | 上述任何文件都可以用内置命令 `zcompile` 预编译(详见 [-> Shell 内建命令](17-builtins.md))。若存在编译文件(以原文件名加 `.zwc` 扩展名形式命名)且比原文件新,会使用编译文件。 30 | -------------------------------------------------------------------------------- /content/06-shell-grammer.md: -------------------------------------------------------------------------------- 1 | # 第六章:Shell 语法 2 | 3 | ## 简单的命令与管道 4 | 5 | 一个简单的命令是一个由空格分开的单词组成的可选的参数赋值序列,且在其中可以使用重定向。有关参数位置的描述,请参见 %% 一节的开头。 6 | 7 | 第一个单词是要执行的命令,其余的单词(如果有)则是该命令的参数。如果给出了命令名称,则在执行命令时,对参数的赋值会改变命令的环境。一个简单命令的值是其返回值,若命令被信号终止,则是128 加上信号编号。例如: 8 | ``` zsh 9 | echo foo 10 | ``` 11 | 是一个带有参数的简单命令。 12 | 13 | 管道既可以是简单命令,也可以是两个或多个简单命令的序列,其中每个命令之间用 `|` 或 `|&` 分隔。如果命令之间用 `|` 分隔,则第一个命令的标准输出将连接到下一个命令的标准输入。 `|&` 是 `2>&1 |` 的简写,它将命令的标准输出和标准错误连接到下一个的标准输入。除非管道前面加有 `!`,管道的值就是最后一条命令的返回值。如果有 `!`,管道的值就是是最后一条命令的返回值的逻辑反。例如, 14 | ```zsh 15 | echo foo | sed 's/foo/bar/' 16 | ``` 17 | 是管道,第一个命令的输出(`foo` 加一个换行符)将传递给第二个命令的输入。 18 | 19 | 如果管道前面带有 `coproc`,则将其作为协进程(coprocess)执行并在它和父 shell 之间建立了一条双向管道。父 shell 可以通过 `>&p` 和 `<&p` 重定向操作符或通过 `print -p` 和 `read -p` 来读取或写入协进程。管道之前不能同时带有 `coproc` 和 `!`。如果启用了作业管理,则可以将协进程视为输入和输出,而不是普通的后台作业。 20 | 21 | 子列表可以是单个管道,也可以是由 `&&` 或 `||` 分隔的两个或多个管道的序列。如果两个管道用 `&&` 分隔,则仅当第一个管道成功(返回零状态)时才执行第二个管道。如果两个管道用 `||` 分隔,则仅当第一个失败(返回非零状态)时才执行第二个管道。两个运算符具有相同的优先级,并且是左结合的。子列表的值是最后执行的管道的值。例如, 22 | ```zsh 23 | dmesg | grep panic && print yes 24 | ``` 25 | 是一个由两个管道组成的子列表,第二个管道只是一个简单命令,仅当 `grep` 命令返回零状态时才会执行。若返回值不为零,则子列表的返回值为第一个的返回值,否则则为 `print` 的返回值(几乎肯定为零)。 26 | 27 | 列表是由以 `;`、`&`、`&|`、`&!` 或换行符结尾的零个或多个子列表的序列。若列表作为出现在圆括号或花括号之间的复杂命令,最后一个子列表的终止符可以省略。当子列表以分号或换行符终止时,shell 将在执行下一个子列表之前等待其完成。如果子列表以 `&`,`&|` 或 `&!` 终止,则 shell 将在后台执行它的最后一个管道,并且不等待其完成(请注意 zsh 与其他 shell 的区别在于 zsh 会在后台执行整个子列表)。在这种情况下,后台管道返回零状态。 28 | 29 | 更一般地,列表可以看作是任何 shell 命令的集合,且包含以下复杂命令。请注意下文中出现“列表”一词时,都隐含这一种情况。例如,shell 函数中的命令形成了一种特殊的列表。 30 | 31 | 32 | ## 前置命令修饰符 33 | 34 | 一个简单命令之前可能会带有前置命令修饰符,该修饰符将会更改命令的解释方式。这些修饰符是 shell 内置命令,但 `nocorrect` 除外,后者是保留字。 35 | 36 | `-` 37 | : 该命令按照 `argv[0]` 字符串前面的追加一个 `-` 执行。 38 | 39 | `builtin` 40 | : 这个命令被视为内建命令执行,而不是通常的会考虑 shell 函数和外部命令。 41 | 42 | `command [ -pvV ]` 43 | : 这个命令被视为外部命令执行,而不会考虑 shell 函数或者内建命令。如果设置了 `POSIX_BUILTINS` 选项,内建命令也会被考虑执行,但是某些特性会被抑制。`-p` 选项可以指示默认的搜索路径,以取代 `$path` 数组。使用 `-v` 选项的话,`command` 的行为类似于 `whence`;使用 `-V` 选项,效果等同于 `whence -v`。 44 | 45 | `exec [ -cl ] [ -a argv0 ]` 46 | : 以下命令以及所有参数将代替当前进程运行,而不是作为子进程运行。shell 不 fork 而被更换。该 shell 不调用 `TRAPEXIT`,也不加载(`source`)`zlogout`。提供这些选项是为了与其他 shell 兼容。 47 | {>>译注:即和 POSIX syscall `exec()` 的表现相似。<<} 48 | `-c` 选项会清理环境。 49 | `-l` 选项效果与 `-` 前置命令修饰符类似,将替代运行的命令作为登录 shell (login shell) 对待,并在其 `argv[0]` 前附加 `-`。该选项与 `-a` 选项一同使用无效。 50 | `-a` 选项用于显式指定替换命令要使用的 `argv[0]` 字符串(命令所看到的自身的名称),并且直接等效于设置 `ARGV0` 环境变量。 51 | 52 | `nocorrect` 53 | : 不会对任何单词进行拼写修正。它必须出现在任何其他前置命令修饰符之前,因为它会在任何解析之前立即被解释。在非交互式(non-interactive) shell 中无效。 54 | 55 | `noglob` 56 | : 不会对任何单词执行文件名生成(globbing)。 57 | 58 | 59 | ## Complex Commands 复杂命令 60 | 61 | zsh 中的复杂命令是以下之一: 62 | 63 | `if` list `then` list [ `elif` list `then` list ] ... [ `else` list ] `fi` 64 | : 执行 `if` 后的列表,如果返回值为零,则执行 `then` 后的列表。否则,将执行 `elif` 后的列表,并且如果 `elif` 后的列表返回值为零,则执行 `then` 后的列表。如果每个 `elif` 后的列表都返回非零值,`else` 后的列表将被执行。 65 | 66 | `for` name ... [ `in` word ... ] term `do` list `done` 67 | : 展开单词列表,然后依次将每个单词设置参数 name ,每次执行列表。如果省略了 `in` word,请使用位置参数代替单词。 68 | term 包含一个或多个换行符或分号作为终止符,并且在省略 `in` word 时是可选的。 69 | 单词列表之前可以出现多个参数 name。如果给出了 N 个参数,则在每次执行循环时,会将下 N 个字分配给相应的参数。如果参数多于其余单词,则将其余参数分别设置为空字符串。当没有剩余的单词分配给名字时,循环的执行结束。`in` 只能作为参数列表中的第一个 name 出现,否则将被视为标记参数列表的结尾。 70 | 71 | `for` `(( [expr1] ; [expr2] ; [expr3] ))` `do` list `done` 72 | : 首先对算术表达式 expr1 求值(请参阅 %%)。反复对算术表达式 expr2 求值,直到其求值为零,并且当算术表达式 expr2 不为零时,执行 list 并求值算术表达式 expr3。如果省略任何表达式,则其行为就像它的值为 1。 73 | 74 | `while` list `do` list `done` 75 | : 只要 `while` 后的列表返回值为零,就一直执行 `do` 后的列表。 76 | 77 | `until` list `do` list `done` 78 | : 只要 `until` 后的列表返回值为非零,就一直执行 `do` 后的列表。 79 | 80 | `repeat` word `do` list `done` 81 | : 扩展 word 并将其视为算术表达式,该表达式的计算结果必须为数字 n。然后执行 n 次列表。 82 | 当 zsh 在模拟另一个 shell 的模式下启动时,默认情况下将禁用重复语法。可以使用命令 `enable -r repeat` 启用它。 83 | 84 | `case` word `in` `[ [(]` pattern `[ |` pattern `] ... )` list `(;;|;&|;|) ]` ... `esac` 85 | : 执行与第一个与 word 匹配的 pattern 相关联的列表(如果有)。pattern 的形式与用于 glob 的形式相同。请参阅 %%。 86 | 还需要注意的是,尽管括号和竖线周围可能会出现空白,并且在这些点处将从图案中去除空白,除非设置了 `SH_GLOB` 选项,带有替代选项(`|`)的整个 pattern 被 shell 视为等同于括号内的一组 pattern。 87 | 空白可能会出现在图案的其他地方;这不会被去除。如果设置了 `SH_GLOB` 选项,则可以将开括号清楚地视为语法的一部分,该表达式将解析为单独的词,并将它们视为严格的替代词(与其他shell一样)。 88 | 如果执行的列表以 `;&` 而不是 `;;` 终止,则还将执行下面的列表。除非到达esac,否则服从列表的终止符规则 `;;`、`;&`或 `;|` 适用。 89 | 如果执行的列表以 `;|` 终止,shell 继续扫描 pattern 以寻找下一个匹配项,执行相应的列表,并将规则应用于相应的终止符 `;;`、`;&` 或 `;|`。请注意,word 不会重新展开;所有适用的 pattern 均使用相同的 word 进行测试。 90 | 91 | `select` name [ `in` word ... term ] `do` list `done` 92 | : 其中term是一个或多个换行符或 `;` 来终止。打印一组单词,每个单词后面都有一个数字。如果省略 `in`,请使用位置参数。如果 shell 是交互式(interactive)的且处于活动状态,或者是标准输入,则将打印 `PROMPT3` 提示符,并从行编辑器中读取一行。如果此行由列出的单词之一的数字组成,则将参数 name 设置为与该数字相对应的单词。如果该行为空,则再次打印选择列表。否则,参数名称的值将设置为 `null`。从标准输入读取的行的内容保存在参数 `REPLY` 中。对每个选择执行列表,直到遇到中断或文件结束。 93 | 94 | `(` list `)` 95 | : 在子 shell (subshell)中执行列表。内置 trap 设置的 trap 在执行列表时会重置为其默认值。 96 | 97 | `{` list `}` 98 | : 执行列表 99 | 100 | `{` try-list `}` `always` `{` always-list `}` 101 | : 首先执行 try-list 。不管错误,还是 try-list 中遇到的中断或继续命令,都执行 always-list。然后,从 try-list 的执行结果继续执行;否则,将继续执行。换句话说,任何错误,中断或继续命令都将以正常方式处理,就像 alwayslist 不存在一样。这两个代码块分别称为“try block”和“always block”。 102 | 可选的换行符或分号可能会出现在 `always` 后面;但是请注意,它们可能不会出现在前面的右大括号和 `always` 之间。 103 | 在这种情况下,“错误”是指诸如语法错误之类的情况,它会导致 shell 中止当前函数,脚本或列表的执行。Shell 解析代码时遇到语法错误,always-list 将不会被执行。例如,错误构造的 try-list 中的 if 块会导致 shell 在解析过程中中止,从而将不会执行 always-list ,而诸如 `${*foo*}` 之类的错误替换会导致运行时错误,之后将执行 always-list。 104 | 可以使用特殊的整数变量 `TRY_BLOCK_ERROR` 测试并重置错误条件。在 always-list 之外,该值无关紧要,但将其初始化为 -1。在 always-list 内,如果 try-list 中发生错误,则值为 1,否则为 0。如果在 always-list 期间将 `TRY_BLOCK_ERROR` 设置为 0,则将重置由 try-list 引起的错误条件,并在 always-list 之后继续执行 shell。在 try-list 期间更改值没有用(除非这构成封闭的 always block 的一部分)。 105 | 无论 `TRY_BLOCK_ERROR` 如何,always-list 末尾调用 `$?` 是从 try-list 返回的值。即使发生错误,即使 `TRY_BLOCK_ERROR` 设置为零,该值也不为零。 106 | 下面的代码执行给定的代码,而忽略其引起的任何错误。这是通过在子 shell 中执行代码来保护代码的常规约定的替代方法。 107 | ```zsh 108 | { 109 | # 可能导致错误的代码 110 | } always { 111 | # 不管错误如何,都将执行此代码。 112 | (( TRY_BLOCK_ERROR = 0 )) 113 | } 114 | # 错误条件已被重置。 115 | ``` 116 | 当 try block 出现在任何函数之外时,try-list 中遇到的返回或退出不会导致 always-list 的执行。相反,在执行任何 EXIT trap 后,shell 会立即退出。否则,在 try-list 中遇到的 return 命令将导致 always-list 的执行,就像中断和继续一样。 117 | 118 | `function` word ... `[ () ] [ term ] {` list `}` 119 | word ... `() [ term ] {` list `}` 120 | word ... `() [ term ]` command 121 | : 其中term是一个或多个换行符或 `;`。定义一个单词可以引用的函数。通常,只提供一个单词;多个单词仅对设置 trap 有用。函数的主体是 `{` 和 `}` 之间的列表。请参阅 %%。 122 | 如果将选项 `SH_GLOB` 设置为与其他 shell 兼容,则当一个 word 时,左右括号之间可能会出现空格;否则,在这种情况下,括号将被视为形成 globbing pattern。 123 | 在上述任何形式中,重定向都可能出现在函数主体外部,例如: 124 | ```zsh 125 | func() { ... } 2>&1 126 | ``` 127 | 重定向与函数一起存储,并在执行函数时应用。重定向中的所有变量都会在执行函数时扩展,但会超出函数范围。 128 | 129 | `time` [ pipeline ] 130 | : 执行管道,并以TIMEFMT参数指定的形式在标准错误报告时序统计信息。如果省略管道,则打印有关 shell 进程及其子进程的统计信息。 131 | 132 | `[[` exp `]]` 133 | : 计算条件表达式 exp,如果为 true ,则返回零。有关 exp 的描述,请参见 %%。 134 | 135 | 136 | ## 复杂命令的替代形式 137 | 138 | zsh 的许多复杂命令都有其他形式。这些是非标准的,即使是对经验丰富的 shell 程序员来说也可能不明显。在不应该考虑 shell 代码可移植性的任何地方都不应使用它们。 139 | 140 | 仅当子列表的格式为 `{ list }` 或设置了 `SHORT_LOOPS` 选项时,以下简短版本才有效。对于 `if`、`while` 和 `until` 命令,在这两种情况下,循环的测试部分也都必须适当地定界,例如用 `[[... ...]]` 或 `(( ... ))` ,否则测试结束将不被认可。对于 `for`、`repeat`、`case` 和 `select` 命令,不需要为参数使用这种特殊形式,但是其他条件(子列表的特殊形式或使用 `SHORT_LOOPS` 选项)仍然适用。 141 | 142 | `if` list `{` list `}` [ `elif` list `{` list `}` ] ... [ `else` `{` list `}` ] 143 | : if的替代形式。上述规则意味着 144 | ```zsh 145 | if [[ -o ignorebraces ]] { 146 | print yes 147 | } 148 | ``` 149 | 可以工作,但 150 | ```zsh 151 | if true { # 不起作用! 152 | print yes 153 | } 154 | ``` 155 | _并不会_ ,因为测试没有适当划分界限。 156 | 157 | `if` list sublist 158 | : 替代 `if` 的简短形式。列表形式的限制与前一形式相同。 159 | 160 | `for` name ... `(` word ... `)`sublist 161 | : `for` 的简短形式。 162 | 163 | `for` name ... [ `in` word ... ] term sublist 164 | : 其中 term 是至少一个换行符或 `;`。 `for` 的另一种简短形式。 165 | 166 | `for` `(( [expr1] ; [expr2] ; [expr3] ))` sublist 167 | : 命令算术的缩写。 168 | 169 | `foreach` name ... `(` word ... `)` list `end` 170 | : `for` 的另一种形式。 171 | 172 | `while` list `{` list `}` 173 | : `while` 的另一种形式。注意上面提到的列表形式的限制。 174 | 175 | `until` list `{` list `}` 176 | : `until` 的另一种形式。注意上面提到的列表形式的限制。 177 | 178 | `repeat` word sublist 179 | : 这是重复的简短形式。 180 | 181 | `case` word `{ [ [(]` pattern `[ |` pattern `]` ... `)` list `(;;|;&|;|) ]` ... `}` 182 | : `case` 的另一种形式。 183 | 184 | `select` name [ `in` word ... term ] sublist 185 | : 其中 term 是至少一个换行符或 `;`。`select` 的简短形式。 186 | 187 | `function` word ... [ `()` ] [ term ] sublist 188 | : 这是函数的简短形式。 189 | 190 | 191 | ## 保留字 192 | 193 | 下列单词用作命令的第一个单词时,将被视为保留单词,除非引用起来或者使用 `disable -r` 对其进行了禁用: 194 | 195 | `do` `done` `esac` `then` `elif` `else` `fi` `for` `case` `if` `while` `function` `repeat` `time` `until` `select` `coproc` `nocorrect` `foreach` `end` `!` `[[` `{` `}` `declare` `export` `float` `integer` `local` `readonly` `typeset` 196 | 197 | 此外,如果未设置 `IGNORE_BRACES` 选项或 `IGNORE_CLOSE_BRACES` 选项,则在任何位置都可以识别 `}`。 198 | 199 | ## 错误 200 | 201 | Shell 会把一些错误认定为严重错误:在交互 Shell 中,这会导致控制返回命令行,在非交互 Shell 中则会导致 Shell 终止。旧版 Zsh 里,运行脚本的非交互 Shell 此时不会完全停止运行,但会在从脚本会读取的下一个命令处继续执行,跳过任何函数的剩余部分或如循环、条件等的 Shell 成分。这个有点反逻辑的行为可以通过选项 `CONTINUE_ON_ERROR` 恢复。 202 | 203 | 非交互 Shell 的严重错误包括: 204 | 205 | * 执行 Shell 时传入的 Shell 参数解析失败 206 | * 用 `set` 内建命令改变选项失败 207 | * 各种解析错误,包括解析数学表达式的失败 208 | * 用 `typeset`,`local`,`declare`,`export`,`integer`,`float` 设定或改变变量行为失败 209 | * 位于不正确位置的循环控制结构(`continue`,`break`)的执行 210 | * 无正则模块时尝试使用正则 211 | * `RESTRICTED` 选项设置时的不允许的操作 212 | * 管线创建时需要的 pipe 创建失败 213 | * Multiio 创建失败 214 | * 声明的 Shell 机能所需的模块自装载失败 215 | * 创建命令或进程替换失败 216 | * Glob 界定符的语法错误 217 | * 未被 `BAD_PATTERN` 选项捕获的文件名生成错误 218 | * Case 语句中用于匹配的所有错误模式 219 | * 不是因为 `NO_MATCH` 或类似选项导致的文件名生成失败 220 | * 用于创建 Multiio 的模式中的所有文件名生成错误 221 | * Shell 检测到的所有内存错误 222 | * Shell 变量不可用的下标 223 | * 对只读变量的赋值尝试 224 | * 与变量有关的逻辑错误,如赋值类型有误 225 | * 使用不可用的变量名 226 | * 变量替换语法中的错误 227 | * `$''` 表达式中字符转换的失败 228 | 229 | 如果设定选项 `POSIX_BUILTINS`,更多与 Shell 内建命令相关的错误会被认定为严重错误,就如 POSIX 标准规定的那样。 230 | 231 | ## 注释 232 | 233 | 非交互 Shell ,或者是设定了选项 `INTERACTIVE_COMMENTS` 的交互 Shell 中,以 `histchar` 参数中的第三个字符(默认是‘`#`’)开头的单词会使那个单词以及其后直至换行的所有字符都被忽略。 234 | 235 | ## 别名 236 | 237 | Shell 输入中的每个合适的 _单词_ 都会被检查其是否存在为它定义的别名。如果有,则在它位于命令位置时(在它会是一个简单命令的第一个单词时),或在它是全局别名时把它替换为别名的内容。如果替换内容以一个空格结尾,Shell 输入的下一个单词永远会被用于别名展开。别名使用 `alias` 内建命令定义。全局别名可以通过那个内建命令的 `-g` 选项定义。 238 | 239 | _单词_ 的定义是: 240 | 241 | * 任何普通字符串或 Glob 模式 242 | * 任何以任何方式引用的字符串(注意这条规则的使用需要引用符号也是别名定义的一部分) 243 | * 任何参数引用或者命令替换 244 | * 任何一系列上述内容,且中间无空格或其它单元 245 | * 任何保留字符(`case`,`do`,`else` 等) 246 | * 在有全局别名的情况下,任何命令分隔符,任何重定向操作符,以及不是 Glob 模式一部分的 ‘`(`’ 和 ‘`)`’ 247 | 248 | Shell 输入的别名展开在除历史展开的其它展开前应用。因此,如果为单词 `foo` 设定了别名,引用这个词的一部分可避免别名展开,如 `\foo`。任何引用形式都可以,尽管也没有任何措施阻止定义像 `\foo` 这样对引用形式定义的别名。 249 | 250 | 当设定 `POSIX_ALIASES` 时,只有普通的未引用的字符串会考虑别名。`alias` 内建命令不会拒绝不被考虑的别名,但它们不会被展开。 251 | 252 | 对于补全来说,因为它会移除后面没有特殊字符的反斜杠,所以先用单个引号引用单词可能更方便,例如 `'foo` 补全时会自动加上尾部的引号。 253 | 254 | ### 别名的问题 255 | 256 | 尽管别名可以像普通 Shell 语法一样使用,不是每个非空白字符都可用作别名。 257 | 258 | 任何不属于上述定义的单词的一系列字符都不会被认为是单词,因此它不会被尝试按别名展开,无论它是如何被定义的(例如使用 %% 中描述的特殊参数 `aliases` 定义的。)然而在上述 `POSIX_ALIASES` 的情况中,Shell 在别名被创建时不会推断该字符串是否属于单词。 259 | 260 | 例如,命令行中在开头包含 `=` 的表达式是一个赋值因而不能按别名展开;单独的 = 并非赋值但只能通过参数设定为别名,因为否则 `=` 被认为是内建命令语法的一部分。 261 | 262 | 目前还不可以将用于引入算术表达式的 `((` 用于别名,因为在整个语句被解析前,它还不能与引入子 Shell 的两个连续的 `(` 区别开来。并且如果像 `&&` 这样的分隔符被别名,`\&&` 会变成两个单元 `\&` 和 `&`,每一个都可能被单独别名。`\<<`、`\>|` 等同理。 263 | 264 | 以下代码展示了一个使用别名时常见的问题; 265 | 266 | ```zsh 267 | alias echobar='echo bar'; echobar 268 | ``` 269 | 270 | 这会输出找不到命令 `echobar` 的消息,发生的原因是别名在代码读取时被展开;整行命令被一次性读取因此当执行 `echobar` 时要展开新定义的别名已经太迟。这种问题通常发生在脚本,函数,以及用 `source` 或 `.` 执行的代码中。鉴于此,非交互代码中推荐使用函数而非别名。 271 | 272 | ## 引用(Quoting) 273 | 274 | 字符可以通过在前面加 `\` 被 _引用_(使得它只表示它自身),后面紧随换行的 `\` 会被忽略。 275 | 276 | 包裹在 `$'` 和 `'` 会按照内建命令 `print` 的方式处理,产生的整个字符串被认为被完全引用,可以用 `\'` 反转义来引入字面的 `'` 字符。 277 | 278 | 包裹在一对前面没有 `$` 的单引号(`'`)的所有字符都被引用。除非设定选项 `RC_QUOTES`,否则单引号内不能再出现单引号,此时两个单引号转变为一个单引号。例如, 279 | 280 | ```zsh 281 | print '''' 282 | ``` 283 | 284 | 在未设定 `RC_QUOTES` 选项时除了换行什么都不输出,而设定是输出一个单引号。 285 | 286 | 在双引号(`""`)内,参数和命令替换可以发生,并且 `\` 可以引用 `\`,`'`,`"`,`$`,以及 `$histchars` 的第一个字符(默认是 `!`)。 287 | -------------------------------------------------------------------------------- /content/07-redirection.md: -------------------------------------------------------------------------------- 1 | # 第七章:重定向 2 | 3 | 如果一个命令后跟着 `&` 且作业控制不生效,该命令默认的标准输入是空文件 `/dev/null`。否则,命令的执行环境会包含 Shell 按照输入 / 输出规范修改的文件描述符。 4 | 5 | 以下的规范可出现在简单命令的任何位置或复杂命令前后。_word_ 或 _digit_ 除非下文有注解,在使用前会发生展开,如果 _word_ 的展开结果包含多于一个的文件名,每个文件名都发生重定向。 6 | 7 | `<` word 8 | : 以读取模式打开 _word_ 并作为标准输入。用这种方式打开不存在的文件会产生错误。 9 | 10 | `<>` word 11 | : 以读写模式打开 _word_ 并作为标准输入。如果文件不存在则创建它。 12 | 13 | `>` word 14 | : 以写入模式打开 _word_ 并作为标准输出。如果文件不存在则创建它。如果文件存在,且 `CLOBBER` 选项未被设定,产生错误;否则文件大小截断为零。 15 | 16 | `>|` word 17 | `>!` word 18 | : 同 `>`,除了无视 `CLOBBER` 无条件在文件存在时将文件长度截断为零。 19 | 20 | `>>` word 21 | : 以追加模式打开 _word_ 并作为标准输出。如果文件不存在,且 `CLOBBER` 和 `APPEND_CREATE` 选项都未被设定,产生错误;否则创建文件。 22 | 23 | `>>|` word 24 | `>>!` word 25 | : 同 `>>`,除了无视 `CLOBBER` 和 `APPEND_CREATE` 无条件在文件不存在时创建文件。 26 | 27 | `<<`[`-`] word 28 | : Shell 开始读取输入,直到读取到和 _word_ 相同的一行,或直到读取到文件结束符。_word_ 中不会发生参数展开,命令替换或文件名生成。产生的被称为 _here-document_ 的文档作为标准输入。 29 | 如果 _word_ 中任何字符被单引号,双引号或者 `\` 引用(Quoted),文档中的字符不会被解析,否则会发生参数和命令替换,紧随换行的 `\` 被移除,并且必须用 `\` 来引用字符 `\`,`$`,`'` 以及 _word_ 的首字符。 30 | 注意 _word_ 不会被 Shell 展开。_word_ 中的反引号({>>`<<})不会发生作用,而是类似于双引号,除了反引号自身会被原封不动地传入。(该信息仅为完整性而提供,不建议使用反引号。)`$'...'` 形式的引用会产生展开反斜杠引用为特殊字符的标准效果。 31 | 如果使用 `<<-`,前面的所有 Tab {>>译注:是 Tab 而不是空格!<<}会从 _word_ 和文档中移除。 32 | 33 | `<<<` word 34 | : Shell 展开 _word_ 并把结果作为标准输入。这被称为 _here-string_。和 Here-Document 中的 _word_ 相比,前者的 _word_ Shell 不展开。产生的结果结尾有换行。 35 | 36 | `<&` number 37 | `>&` number 38 | : 标准输入 / 输出从以 _number_ 表示的文件描述符(数字)复制(见 dup2(2))。 39 | 40 | `<& -` 41 | `>& -` 42 | : 关闭标准输入 / 输出。 43 | 44 | `<& p` 45 | `>& p` 46 | : 从协程的输入 / 到协程的输出移动到标准输入 / 输出。 47 | 48 | `>&` word 49 | `&>` word 50 | : (除非 `>& word` 符合上述语法;可使用 `&>` 避免歧义。)同时将标准输出和标准错误(文件描述符 2)以 `> word` 的形式重定向。注意 Multios(见下)情况下它 _不_ 产生和 `> word 2>&1` 一样的效果。 51 | 52 | `>&|` word 53 | `>&!` word 54 | `&>|` word 55 | `&>!` word 56 | : 同时将标准输出和标准错误(文件描述符 2)以 `>| word` 的形式重定向。 57 | 58 | `>>&` word 59 | `&>>` word 60 | : 同时将标准输出和标准错误(文件描述符 2)以 `>> word` 的形式重定向。 61 | 62 | `>>&|` word 63 | `>>&!` word 64 | `&>>|` word 65 | `&>>!` word 66 | : 同时将标准输出和标准错误(文件描述符 2)以 `>>| word` 的形式重定向。 67 | 68 | 如果以上任一语法前有数字,则使用的文件描述符是该数字指定的文件描述符而非默认的 0 或 1。指定重定向的顺序非常重要。Shell 按照(_文件描述符_,_文件_)关联的方式处理每个重定向。例如: 69 | 70 | ```zsh 71 | ... 1>fname 2>&1 72 | ``` 73 | 74 | 首先将文件描述符 1 与 _fname_ 关联。然后将文件描述符 2 与文件描述符 1 关联的文件(_fname_)关联。若调换重定向顺序,文件描述符 2 将与终端关联(假定文件描述符 1 此时已经如此关联)且文件描述符 1 与文件 _fname_ 关联。 75 | 76 | [-> 简单的命令与管道](06-shell-grammer.md#_1) 中描述的分隔符 `|&` 是 `2>&1 |` 的简写。 77 | 78 | 进程替换的多种形式,即用于输入的 `<(list)` 和 `=(list)` 以及用于输出的 `>(list)`,常与重定向一起使用。例如,如果输出重定向中的 _word_ 是 `>(list)` 形式,输出被管道到 _list_ 表示的命令。详见 %%。 79 | 80 | ## 用参数打开文件描述符 81 | 82 | 当 Shell 将参数解析成命令时,且 Shell 选项 `IGNORE_BRACES` 未被设置时,可以使用另一种形式的重定向:操作符前可以不是数字而是花括号{>>{}<<}表示的有效 Shell 标识符。Shell 会打开一个新的保证数字至少为 10 的文件描述符并将标识符指向的参数设定为打开的文件描述符。闭合花括号和重定向字符间不能有空格。例如: 83 | 84 | ```zsh 85 | ... {myfd}>&1 86 | ``` 87 | 88 | 这会打开一个新的文件描述符,其是文件描述符 1 的复制,并把参数 `myfd` 设定成该文件描述符的至少为 10 的数字。可以用 `>&$myfd` 语法写入新文件描述符。该文件描述符在子 Shell 和产生的外部可执行文件中保持打开状态。 89 | 90 | `{varid}>&-` 语法,例如 `{myfd}>&-`,可以用于关闭用这种方法打开的文件描述符。注意这种情况下 _varid_ 指定的参数此前必须设定成文件描述符。 91 | 92 | 参数只读时用这种方法打开或关闭文件描述符会产生错误。然而如果 _param_ 只读,用 `<&$`_param_ 或 `>&$`_param_ 读写文件描述符不产生错误。 93 | 94 | 如果未设定选项 `CLOBBER`,用一个此前已经通过这种方式设定为打开的文件描述符的参数打开文件描述符会产生错误。在用该参数打开文件描述符前取消设定参数可避免这一错误。 95 | 96 | 注意这种方式只分配或关闭文件描述符;它不会执行任何从它或到它的重定向。使用用于 `exec` 的文件描述符前分配它通常会很方便。这个语法当用在像括号内子 Shell 或循环这样的复杂命令周围时无论如何都不会工作,因为此时打开的花括号被解析为当前 Shell 里执行的命令列表的一部分。 97 | 98 | 以下展示了一个通常的分配,使用,关闭文件描述符的例子: 99 | 100 | ```zsh 101 | integer myfd 102 | exec {myfd}>~/logs/mylogfile.txt 103 | print This is a log message. >&$myfd 104 | exec {myfd}>&- 105 | ``` 106 | 107 | 注意表达式 `>&$myfd` 中变量的展开在重定向打开时发生。这是在命令参数的展开以及此前的重定向被处理之后产生的。 108 | 109 | ## Multios 110 | 111 | 如果用户尝试多次打开一个文件描述符用于写入,Shell 会把文件描述符打开为一个像 _tee_ 一样复制输入到所有指定输出的管道,前提是选项 `MULTIOS` 被设定,而它默认被设定。因此: 112 | 113 | ```zsh 114 | date >foo >bar 115 | ``` 116 | 117 | 向两个名为 `foo` 和 `bar` 的文件写入日期。注意管道隐含重定向;因此 118 | 119 | ```zsh 120 | date >foo | cat 121 | ``` 122 | 123 | 将日期写入到文件 `foo`,还把它管道到 cat。 124 | 125 | 注意 Shell 打开所有用于 Multio 进程的所有文件,而不是在它们要被写入时。 126 | 127 | 注意重定向永远按顺序展开,这是无视 `MULTIOS` 设定永远发生的事情,但该选项产生效果时会有额外的影响。例如,表达式 `>&1` 的含义会在上一个重定向后发生改变: 128 | 129 | ```zsh 130 | date >&1 >output 131 | ``` 132 | 133 | 上一例子中,`>&1` 在这一行的开头指向标准输出;结果与命令 `tee` 类似,然而,考虑以下: 134 | 135 | ```zsh 136 | date >output >&1 137 | ``` 138 | 139 | 由于重定向按顺序执行,当遇到 `>&1` 时标准输入已经设定为文件 `output` 从而另一份输出也写入到那个文件。这可能不是预期行为。 140 | 141 | 如果设定 `MULTIOS`,重定向操作符后的单词还会发生文件名生成(Globbing)。因此 142 | 143 | ```zsh 144 | : > * 145 | ``` 146 | 147 | 截断当前目录所有文件,假设至少有一个。(没有选项 `MULTIOS` 时会产生空文件 `*`。)类似地,你可以 148 | 149 | ```zsh 150 | echo exit 0 >> *.sh 151 | ``` 152 | 153 | 如果用户尝试多次打开一个文件描述符用于读取,Shell 会把文件描述符打开为一个复制所有指定输入到其输出的管道,前提是选项 `MULTIOS` 被设定。注意所有文件都被立即打开,而不是在它们要被读取时。这与 `cat` 行为不同,所以如果需要严格的标准行为,应该使用 `cat`。 154 | 155 | 因此 156 | 157 | ```zsh 158 | sort &$myfd` 中变量展开时。 170 | 171 | 注意管道隐含重定向;因此 172 | 173 | ```zsh 174 | cat bar | sort bar > baz 183 | ``` 184 | 185 | 在未设置 `MULTIOS` 时截断 `bar`,向 `baz` 写入 `Hello`。 186 | 187 | 输出 Multio 接入外部程序时有一个问题,一个简单的例子展示了这一点: 188 | 189 | ```zsh 190 | cat file >file1 >file2 191 | cat file1 file2 192 | ``` 193 | 194 | 这里,第二个 `cat` 有可能不能完整输出 `file1` 和 `file2` 的内容(即 `file` 原始内容重复两次)。 195 | 196 | 这种情况发生的原因是 Multios 在 `cat` 进程从父 Shell 中分叉时产生,所以父 Shell 不等待 Multios 写入完数据。这意味着上述命令可能在 `file1` 和 `file2` 完全写入前就退出。为绕过此问题,可以把 `cat` 进程运行为当前 Shell 的一个作业: 197 | 198 | ```zsh 199 | { cat file } >file >file2 200 | ``` 201 | 202 | 这里 `{...}` 作业等待两个文件都写入完毕。 203 | 204 | ## 无命令重定向 205 | 206 | 如果一个简单命令包含一个或多个重定向操作符以及零或多个参数赋值,但没有命令名,Zsh 有多种表现行为。 207 | 208 | 如果未设定参数 `NULLCMD` 或选项 `CSH_NULLCMD` 被设定,产生错误。这是 _csh_ 默认行为且模拟 _csh_ 时 `CSH_NULLCMD` 被默认设定。 209 | 210 | 如果设定选项 `SH_NULLCMD`,内建命令 `:` 被插入为命令,继承给定重定向。这是模拟 _sh_ 或 _ksh_ 默认行为。 211 | 212 | 否则,如果设定参数 `NULLCMD`,它的值作为命令,继承给定重定向。如果同时设定 `NULLCMD` 和 `READNULLCMD`,如果重定向是输入则使用后者而非前者。`NULLCMD` 默认是 `cat` 而 `READNULLCMD` 默认是 `more`。因此 213 | 214 | ```zsh 215 | < file 216 | ``` 217 | 218 | 在标准输出上显示 `file` 内容,在终端时带分页。`NULLCMD` 和 `READNULLCMD` 可指向 Shell 函数。 219 | -------------------------------------------------------------------------------- /content/08-command-execution.md: -------------------------------------------------------------------------------- 1 | # 第八章:运行命令 2 | -------------------------------------------------------------------------------- /content/09-functions.md: -------------------------------------------------------------------------------- 1 | # 第九章:函数 2 | -------------------------------------------------------------------------------- /content/10-jobs-and-signals.md: -------------------------------------------------------------------------------- 1 | # 第十章:任务控制与信号量 2 | -------------------------------------------------------------------------------- /content/11-atithmetics.md: -------------------------------------------------------------------------------- 1 | # 第十一章:算术扩展 2 | -------------------------------------------------------------------------------- /content/12-conditionals.md: -------------------------------------------------------------------------------- 1 | # 第十二章:条件表达式 2 | -------------------------------------------------------------------------------- /content/13-prompt-expns.md: -------------------------------------------------------------------------------- 1 | # 第十三章:提示符展开 2 | -------------------------------------------------------------------------------- /content/14-expansions.md: -------------------------------------------------------------------------------- 1 | # 第十四章:展开 2 | -------------------------------------------------------------------------------- /content/15-parameters.md: -------------------------------------------------------------------------------- 1 | # 第十五章:参数 2 | -------------------------------------------------------------------------------- /content/16-options.md: -------------------------------------------------------------------------------- 1 | # 第十六章:选项 2 | -------------------------------------------------------------------------------- /content/17-builtins.md: -------------------------------------------------------------------------------- 1 | # 第十七章:Shell 内建命令 2 | -------------------------------------------------------------------------------- /content/18-zle-line-editor.md: -------------------------------------------------------------------------------- 1 | # 第十八章:ZLE 行编辑器 2 | -------------------------------------------------------------------------------- /content/19-completion-widgets.md: -------------------------------------------------------------------------------- 1 | # 第十九章:补全部件 2 | -------------------------------------------------------------------------------- /content/20-completion-system.md: -------------------------------------------------------------------------------- 1 | # 第二十章:补全系统 2 | -------------------------------------------------------------------------------- /content/21-compctl-completions.md: -------------------------------------------------------------------------------- 1 | # 第二十一章:基于 `compctl` 的补全系统 2 | -------------------------------------------------------------------------------- /content/22-zsh-modules.md: -------------------------------------------------------------------------------- 1 | # 第二十二章:Zsh 模块 2 | -------------------------------------------------------------------------------- /content/23-zcal-calendar.md: -------------------------------------------------------------------------------- 1 | # 第二十三章:日历函数系统 2 | -------------------------------------------------------------------------------- /content/24-ztcp-tcpsocket.md: -------------------------------------------------------------------------------- 1 | # 第二十四章:TCP 函数系统 2 | -------------------------------------------------------------------------------- /content/25-zftp-ftpclient.md: -------------------------------------------------------------------------------- 1 | # 第二十五章:Zftp 函数系统 2 | -------------------------------------------------------------------------------- /content/26-user-contrib.md: -------------------------------------------------------------------------------- 1 | # 第二十六章:用户贡献 2 | -------------------------------------------------------------------------------- /content/index.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | 一份完整的 Zsh 中文手册。 4 | 5 | --- 6 | 7 | Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies. 8 | 9 | Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one. 10 | 11 | Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions. 12 | 13 | --- 14 | 15 | ## 进度 16 | 17 | - [x] 1 The Z Shell Manual 18 | - [x] 2 Introduction 19 | - [x] 3 Roadmap 20 | - [x] 4 Invocation 21 | - [x] 5 Files 22 | - [x] 6 Shell Grammar 23 | - [x] 7 Redirection 24 | - [ ] 8 Command Execution 25 | - [ ] 9 Functions 26 | - [ ] 10 Jobs & Signals 27 | - [ ] 11 Arithmetic Evaluation 28 | - [ ] 12 Conditional Expressions 29 | - [ ] 13 Prompt Expansion 30 | - [ ] 14 Expansion 31 | - [ ] 15 Parameters 32 | - [ ] 16 Options 33 | - [ ] 17 Shell Builtin Commands 34 | - [ ] 18 Zsh Line Editor 35 | - [ ] 19 Completion Widgets 36 | - [ ] 20 Completion System 37 | - [ ] 21 Completion Using compctl 38 | - [ ] 22 Zsh Modules 39 | - [ ] 23 Calendar Function System 40 | - [ ] 24 TCP Function System 41 | - [ ] 25 Zftp Function System 42 | - [ ] 26 User Contributions 43 | 44 | ## Project layout 45 | 46 | mkdocs.yml # The configuration file. 47 | content/ 48 | index.md # The documentation homepage. 49 | ... # Other markdown pages, images and other files. 50 | -------------------------------------------------------------------------------- /content/stylesheets/extra.css: -------------------------------------------------------------------------------- 1 | @import 'https://cdn.jsdelivr.net/npm/@fontsource/jost/latin.css'; 2 | 3 | :root { 4 | --md-text-font: "Jost"; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /mkdocs.yml: -------------------------------------------------------------------------------- 1 | site_name: Zsh 中文手册 2 | site_author: '夜坂雅' 3 | site_url: 'https://shadowrz.github.io/zshdocs-zh/' 4 | docs_dir: 'content' 5 | repo_url: https://github.com/ShadowRZ/zshdocs-zh 6 | repo_name: 'ShadowRZ/zshdocs-zh' 7 | copyright: '2020-2022 夜坂雅及其他贡献者' 8 | extra_css: 9 | - stylesheets/extra.css 10 | 11 | theme: 12 | language: 'zh' 13 | name: 'material' 14 | palette: 15 | - scheme: default 16 | media: "(prefers-color-scheme: light)" 17 | primary: 'deep orange' 18 | accent: 'blue' 19 | toggle: 20 | icon: material/lightbulb-outline 21 | name: 切换为暗色模式 22 | - scheme: slate 23 | media: "(prefers-color-scheme: dark)" 24 | primary: 'deep orange' 25 | accent: 'blue' 26 | toggle: 27 | icon: material/lightbulb 28 | name: 切换为亮色模式 29 | icon: 30 | repo: 'fontawesome/brands/github-alt' 31 | logo: 'fontawesome/solid/terminal' 32 | features: 33 | - toc.integrate 34 | plugins: 35 | - search 36 | - git-revision-date-localized: 37 | type: iso_datetime 38 | - minify: 39 | minify_html: true 40 | markdown_extensions: 41 | - toc: 42 | permalink: true 43 | - codehilite: 44 | guess_lang: false 45 | - admonition 46 | - footnotes 47 | - pymdownx.betterem: 48 | smart_enable: all 49 | - pymdownx.caret 50 | - pymdownx.critic 51 | - pymdownx.details 52 | - pymdownx.emoji: 53 | emoji_index: !!python/name:materialx.emoji.twemoji 54 | emoji_generator: !!python/name:materialx.emoji.to_svg 55 | - pymdownx.keys 56 | - pymdownx.highlight 57 | - pymdownx.superfences 58 | - pymdownx.inlinehilite 59 | - pymdownx.magiclink 60 | - pymdownx.smartsymbols 61 | - pymdownx.tasklist: 62 | custom_checkbox: true 63 | - pymdownx.tilde 64 | - pymdownx.escapeall 65 | - markdown.extensions.def_list 66 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | mkdocs-minify-plugin 2 | mkdocs-git-revision-date-localized-plugin 3 | mkdocs 4 | mkdocs-material 5 | --------------------------------------------------------------------------------