[{"data":1,"prerenderedAt":21},["ShallowReactive",2],{"article-zsh使用技巧":3},{"id":4,"title":5,"slug":6,"description":7,"content":8,"coverImage":9,"tags":10,"category":7,"categoryName":7,"draft":12,"reviewStatus":13,"viewCount":14,"readingTime":15,"author":16,"createdAt":19,"updatedAt":20,"series":7},"26","Zsh使用技巧","zsh使用技巧",null,"\n# Zsh使用技巧\n\n> Zsh 是功能最丰富的交互式 Shell 之一，开箱即用的补全、通配符和历史机制远超 Bash。本文整理日常高频使用的 Zsh 技巧，帮助提升命令行效率。\n\n---\n\n## 1. Tab 补全增强\n\nZsh 的补全系统（completion system）是其最强大的特性之一，通过少量配置即可大幅提升体验。\n\n### 1.1 大小写不敏感补全\n\n默认情况下补全是大小写敏感的，输入 `pdf` 无法补全 `PDF` 文件。在 `~\u002F.zshrc` 中添加：\n\n```bash\n# 大小写不敏感补全\nzstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}'\n```\n\n原理：`matcher-list` 定义了补全匹配规则，`m:{a-zA-Z}={A-Za-z}` 表示将小写字母映射到大写、大写映射到小写进行匹配。\n\n### 1.2 菜单选择模式\n\n默认补全是循环切换候选项，开启菜单选择后可以用方向键在列表中挑选：\n\n```bash\n# 开启菜单选择补全，支持方向键导航\nzstyle ':completion:*' menu select\n```\n\n按 Tab 触发补全后，候选项以列表展示，用方向键或 Tab\u002FShift+Tab 上下移动选择。\n\n### 1.3 Fuzzy 匹配补全\n\n允许输入部分字符就能匹配，比如输入 `fbr` 补全到 `foobar`：\n\n```bash\n# fuzzy 匹配：允许跳过中间字符\nzstyle ':completion:*' matcher-list 'm:{a-zA-Z}={A-Za-z}' 'r:|[._-]=* r:|=*' 'l:|=* r:|=*'\n```\n\n- 第二条规则 `r:|[._-]=*` 允许在 `.` `_` `-` 处进行部分匹配\n- 第三条规则 `l:|=* r:|=*` 允许在任意位置进行前缀匹配\n\n### 1.4 补全缓存与颜色\n\n```bash\n# 启用补全缓存，加速补全响应（如 ssh 主机名补全）\nzstyle ':completion:*' use-cache on\nzstyle ':completion:*' cache-path ~\u002F.zcompcache\n\n# 补全列表带颜色\nzstyle ':completion:*' list-colors ${(s.:.)LS_COLORS}\n```\n\n---\n\n## 2. 历史搜索与快捷键\n\nZsh 的历史机制支持增量搜索、历史扩展等多种方式快速复用命令。\n\n### 2.1 基于上下箭头的前缀搜索\n\n默认行为是按时间遍历历史。开启前缀匹配后，输入 `git` 再按上箭头，只会看到以 `git` 开头的历史命令：\n\n```bash\n# 在 ~\u002F.zshrc 中绑定上下箭头为前缀历史搜索\nautoload -U up-line-or-beginning-search\nautoload -U down-line-or-beginning-search\nzle -N up-line-or-beginning-search\nzle -N down-line-or-beginning-search\nbindkey '^[[A' up-line-or-beginning-search    # 上箭头\nbindkey '^[[B' down-line-or-beginning-search  # 下箭头\n```\n\n### 2.2 Ctrl+R 增量搜索\n\n`Ctrl+R` 是最常用的历史搜索方式，输入关键词即可实时过滤匹配的历史命令。多次按 `Ctrl+R` 可以在多个匹配结果间跳转。\n\nZsh 原生支持此功能，配合 `fzf`（见第 7 章）可以获得更强大的模糊搜索体验。\n\n### 2.3 历史扩展操作符\n\n| 语法 | 含义 | 示例 |\n|------|------|------|\n| `!!` | 上一条完整命令 | `sudo !!` — 用 sudo 重跑上一条 |\n| `!$` | 上一条命令的最后一个参数 | `mkdir foo && cd !$` |\n| `!*` | 上一条命令的所有参数 | `echo a b c` → `print !*` 输出 `a b c` |\n| `!^` | 上一条命令的第一个参数 | — |\n| `!n` | 历史中第 n 条命令 | `!100` 执行第 100 条 |\n| `!pattern` | 最近一条以 pattern 开头的命令 | `!git` 执行最近的 git 命令 |\n| `^old^new` | 替换上一条命令中的文本 | `^foo^bar` 把上一条的 foo 换成 bar |\n\n### 2.4 历史配置\n\n```bash\n# 历史文件与容量\nHISTFILE=~\u002F.zsh_history\nHISTSIZE=50000          # 内存中保留的命令数\nSAVEHIST=50000          # 写入文件的最大条数\n\n# 去重与格式\nsetopt HIST_IGNORE_ALL_DUPS   # 去除连续重复命令\nsetopt HIST_SAVE_NO_DUPS      # 写入文件时也去重\nsetopt HIST_IGNORE_SPACE      # 空格开头的命令不记录（适合敏感命令）\nsetopt SHARE_HISTORY           # 多终端共享历史\n```\n\n---\n\n## 3. 别名系统\n\nZsh 在 Bash alias 的基础上增加了 **global alias** 和 **suffix alias**，覆盖更多场景。\n\n### 3.1 普通别名\n\n```bash\n# 常用命令缩写\nalias ll='ls -alh'\nalias gs='git status'\nalias gp='git push'\n```\n\n### 3.2 Global Alias\n\n普通 alias 只能出现在命令开头，而 **global alias** 可以出现在命令的任意位置，会被全局替换：\n\n```bash\n# 将管道常用操作定义为 global alias\nalias -g G='| grep'\nalias -g L='| less'\nalias -g H='| head'\nalias -g T='| tail'\nalias -g W='| wc -l'\nalias -g S='| sort'\nalias -g N='2>\u002Fdev\u002Fnull'\n\n# 使用示例\ndmesg G usb          # 等价于 dmesg | grep usb\ncat logfile L        # 等价于 cat logfile | less\nfind \u002F -name \"*.log\" N W   # 等价于 find \u002F -name \"*.log\" 2>\u002Fdev\u002Fnull | wc -l\n```\n\n### 3.3 Suffix Alias\n\n根据文件扩展名自动选择打开方式：\n\n```bash\n# 定义后缀别名\nalias -s py=vim       # 直接输入 xxx.py 就用 vim 打开\nalias -s md=code      # .md 文件用 VS Code 打开\nalias -s pdf=zathura  # .pdf 文件用 zathura 打开\nalias -s tar.gz='tar tzf'  # 直接查看压缩包内容\n\n# 使用示例：直接在终端输入文件名\n# .\u002Fscript.py  → 自动用 vim 打开\n# README.md    → 自动用 VS Code 打开\n```\n\n---\n\n## 4. 通配符与文件匹配\n\nZsh 的通配符（globbing）能力远超 Bash，无需 `find` 命令即可完成复杂文件匹配。\n\n### 4.1 递归通配符 `**`\n\n```bash\n# 匹配当前目录及所有子目录下的 .java 文件\nls **\u002F*.java\n\n# 匹配所有子目录下的 Makefile\ncat **\u002FMakefile\n\n# 配合 ** 和目录限定符\nls **\u002Fsrc\u002F          # 所有名为 src 的目录\n```\n\n需开启 `GLOB_STAR_SHORT` 选项才能单独使用 `**`（不含 `*`）：\n\n```bash\nsetopt GLOB_STAR_SHORT   # 允许 ** 单独匹配\n```\n\n### 4.2 限定符（Glob Qualifiers）\n\n限定符写在 `()` 中，用于按文件类型、权限、大小等条件过滤：\n\n| 限定符 | 含义 | 示例 |\n|--------|------|------|\n| `*(.)` | 仅普通文件 | `ls *(.)` |\n| `*(\u002F)` | 仅目录 | `ls *(\u002F)` |\n| `*(x)` | 有可执行权限的文件 | `ls bin\u002F(x)` |\n| `*(.x)` | 普通文件 + 可执行 | `ls *(.x)` |\n| `*(L0)` | 空文件（大小为 0） | `rm *(L0)` |\n| `*(L+1m)` | 大于 1MB 的文件 | `ls *(L+1m)` |\n| `*(m-7)` | 7 天内修改过的文件 | `ls *(m-7)` |\n| `*(om[1,5])` | 按修改时间排序取前 5 个 | `ls *(om[1,5])` |\n| `*(*.)` | 可执行普通文件 | `which **\u002F*(.)` |\n\n```bash\n# 删除所有空目录\nrmdir *(\u002F^F)    # \u002F 表示目录，^F 表示非空取反（即空目录）\n\n# 找出最近修改的 3 个文件\nls -lt *(om[1,3])\n\n# 列出大于 100KB 的 .log 文件\nls **\u002F*.log(L+100k)\n```\n\n### 4.3 否定与分组\n\n```bash\n# ^ 取反：匹配不以 .bak 结尾的文件\nls ^*.bak\n\n# 匹配 .py 或 .sh 文件\nls *.(py|sh)\n```\n\n需开启 `EXTENDED_GLOB` 选项：\n\n```bash\nsetopt EXTENDED_GLOB    # 启用 ^ 取反和 # 等高级通配\n```\n\n---\n\n## 5. 重定向与多命令操作\n\n### 5.1 多命令连接\n\n| 操作符 | 含义 | 示例 |\n|--------|------|------|\n| `&&` | 前一条成功才执行下一条 | `mkdir foo && cd foo` |\n| `\\|\\|` | 前一条失败才执行下一条 | `cd foo \\|\\| echo \"目录不存在\"` |\n| `;` | 顺序执行，不管成功失败 | `echo a; echo b` |\n| `&` | 后台执行 | `sleep 100 &` |\n\n### 5.2 多重重定向与 tee\n\n```bash\n# 同时输出到终端和文件\nmake 2>&1 | tee build.log\n\n# 将输出和错误分别写入不同文件\ncommand > output.log 2> error.log\n\n# Zsh 特有：同时重定向到多个目标\necho hello >file1 >file2    # 两个文件都写入 \"hello\"\n```\n\n### 5.3 Process Substitution\n\n进程替换将命令的输出作为临时文件传给另一个命令，这是处理管道无法胜任场景的关键技巧：\n\n```bash\n# 对比两个命令的输出（类似 diff 两个文件）\ndiff \u003C(sort file1.txt) \u003C(sort file2.txt)\n\n# 将进程输出作为参数传递\nwc -l \u003C(grep \"ERROR\" app.log)\n\n# 同时查看标准输出和错误\ncommand > >(tee stdout.log) 2> >(tee stderr.log)\n```\n\n原理：`\u003C(command)` 在 `\u002Fdev\u002Ffd\u002F` 下创建一个临时文件描述符，其他命令可以像读文件一样读取它。\n\n---\n\n## 6. 内建命令与变量操作\n\n### 6.1 typeset 声明变量\n\n`typeset` 是 Zsh 中声明变量的核心命令（`declare`、`local`、`export` 等都是它的别名或子集）：\n\n```bash\ntypeset -i count=0          # 声明整数变量\ntypeset -a arr=(a b c)      # 声明数组\ntypeset -A map=([k1]=v1 [k2]=v2)  # 声明关联数组（字典）\ntypeset -r CONST=100        # 声明只读变量\ntypeset -x PATH             # 导出为环境变量（等同于 export）\ntypeset -U path             # 去重：path 数组自动去除重复路径\n```\n\n### 6.2 参数展开（Parameter Expansion）\n\nZsh 支持丰富的字符串操作，无需调用 `sed` 或 `awk`：\n\n```bash\nname=\"hello_world.txt\"\n\n# 长度\necho ${#name}           # 15\n\n# 默认值\necho ${undefined:-default}   # 输出 default\n\n# 前缀\u002F后缀删除\necho ${name#hello_}     # world.txt（删除最短前缀）\necho ${name##*_}        # world.txt（删除最长前缀）\necho ${name%.txt}       # hello_world（删除最短后缀）\necho ${name%%.*}        # hello_world（删除最长后缀）\n\n# 替换\necho ${name\u002Fworld\u002FWORLD}   # hello_WORLD.txt（首次替换）\necho ${name\u002F\u002F_\u002F - }        # hello - world.txt（全局替换）\n\n# 大小写转换（Zsh 专属语法）\necho ${(U)name}         # HELLO_WORLD.TXT（转大写）\necho ${(L)name}         # hello_world.txt（转小写）\necho ${name:u}           # HELLO_WORLD.TXT（转大写，简写形式）\n```\n\n### 6.3 数组操作\n\n```bash\narr=(apple banana cherry)\n\necho ${arr[1]}          # apple（Zsh 数组从 1 开始，注意与 Bash 不同）\necho ${arr[-1]}         # cherry（倒数第一个）\necho ${arr[2,3]}        # banana cherry（切片）\necho ${#arr[@]}         # 3（数组长度）\necho ${^arr}.log        # apple.log banana.log cherry.log（逐元素扩展）\n```\n\n> Zsh 数组下标从 **1** 开始，而 Bash 从 **0** 开始，这是两者的重要差异。\n\n---\n\n## 7. 插件与框架推荐\n\n### 7.1 框架选择\n\n| 框架 | 特点 | 适合场景 |\n|------|------|----------|\n| **oh-my-zsh** | 社区最大、插件主题丰富、开箱即用 | 新手入门、快速配置 |\n| **zinit** | 按需延迟加载（turbo mode），启动极快 | 追求启动速度的高级用户 |\n| **znap** | 轻量极简，自动编译缓存，配置简洁 | 喜欢精简配置的用户 |\n\n> 不建议同时使用多个框架，选一个即可。\n\n### 7.2 必装插件\n\n**zsh-autosuggestions** — 基于历史自动提示命令：\n\n```bash\n# zinit 安装方式\nzinit light zsh-users\u002Fzsh-autosuggestions\n\n# 效果：输入命令时会自动灰度提示历史匹配\n# 按 → 或 End 接受建议，继续输入则忽略\n```\n\n**zsh-syntax-highlighting** — 实时语法高亮：\n\n```bash\nzinit light zsh-users\u002Fzsh-syntax-highlighting\n\n# 效果：有效命令显示绿色，无效命令显示红色\n# 路径存在时下划线标出，引号不匹配时标红\n```\n\n**fzf** — 模糊搜索神器（严格说是独立工具，但与 Zsh 深度集成）：\n\n```bash\n# 安装 fzf 及其 Zsh 集成\ngit clone --depth 1 https:\u002F\u002Fgithub.com\u002Fjunegunn\u002Ffzf ~\u002F.fzf\n~\u002F.fzf\u002Finstall\n\n# Ctrl+T：模糊搜索文件并插入路径\n# Ctrl+R：模糊搜索历史命令\n# Alt+C：模糊跳转目录\n```\n\n### 7.3 实用插件清单\n\n| 插件 | 功能 |\n|------|------|\n| `zsh-completions` | 额外补全定义（cargo、pip、docker 等） |\n| `z` \u002F `zoxide` | 智能目录跳转，根据访问频率排序 |\n| `sudo` | 双击 Esc 自动在命令前加 sudo |\n| `copypath` | 快速复制当前目录路径到剪贴板 |\n| `dirhistory` | Alt+左\u002F右箭头浏览目录历史 |\n| `extract` | 一条 `extract` 命令解压所有格式 |\n\n---\n\n## 8. 实用快捷键速查表\n\n### 8.1 编辑快捷键\n\n| 快捷键 | 功能 |\n|--------|------|\n| `Ctrl+A` | 光标移到行首 |\n| `Ctrl+E` | 光标移到行尾 |\n| `Ctrl+W` | 删除光标前一个单词 |\n| `Ctrl+U` | 删除光标前全部内容 |\n| `Ctrl+K` | 删除光标后全部内容 |\n| `Ctrl+Y` | 粘贴最近删除的内容 |\n| `Alt+.` | 插入上一条命令的最后一个参数（等同于 `!$`） |\n| `Ctrl+L` | 清屏 |\n| `Ctrl+_` | 撤销上一次编辑 |\n\n### 8.2 进程控制快捷键\n\n| 快捷键 | 功能 |\n|--------|------|\n| `Ctrl+C` | 中断当前命令 (SIGINT) |\n| `Ctrl+Z` | 挂起当前命令，用 `fg` 恢复前台、`bg` 恢复后台 |\n| `Ctrl+D` | 发送 EOF，退出当前 Shell 或结束输入 |\n\n### 8.3 常用组合技\n\n```bash\n# 清屏并保留历史\nCtrl+L\n\n# 杀掉占用端口的进程\nkill $(lsof -ti:8080)\n\n# 快速回到上一个工作目录\ncd -\n\n# 用 Alt+. 循环获取历史命令的参数\n# 每按一次 Alt+. 就回溯更早的一条命令的最后一个参数\n```\n\n---\n\n## 相关阅读\n\n- [[正则表达式]] — 命令行中频繁使用正则进行文本处理\n- [[Git]] — Git 的交互式操作依赖 Shell 环境\n","https:\u002F\u002Fimg.233144.xyz\u002Fxv-site\u002F124c539f-1c77-49f7-a8bb-f59af995d72c.jpg",[11],"Linux",false,"APPROVED",55,18,{"id":17,"username":18},"4","c","2026-05-20T17:25:15.990978","2026-05-29T12:04:08.939568",1780059956182]