nushell(简称 Nu)是一款用 Rust 编写的跨平台现代 shell,最大的不同在于:传统 shell 把一切当作纯文本来传递,而 nushell 把命令输出当成结构化表格。这意味着你不用再写复杂的 grep、awk、cut 管道来“抠”字段,而是像操作数据库一样筛选、排序、投影命令结果。本文用一组可直接复制运行的示例,带你把日常命令行工作流升级成结构化管道。
一、为什么文本管道会越写越痛
在 bash 里,想找出当前目录里大于 1MB 的文件,你大概会写出 ls -la | awk '$5>1048576' 之类的组合。问题不在于记不住 awk 语法,而在于每一条命令都把上一条的输出当成“一串字符”,你必须为每个工具的字段分隔方式重新适配。当来源从本地文件变成进程列表、网络请求、JSON 接口时,文本处理的脆弱性会被迅速放大。
举个更典型的例子:你想从 docker inspect 返回的 JSON 里提取某个容器的 IP 地址。在 bash 里你往往要借助 jq 或者一串 grep -oP,而 jq 的语法本身又是一门需要单独学习的语言。nushell 则把 JSON 直接当成一等公民:docker inspect <id> | from json | get 0.NetworkSettings.IPAddress,整条管道都是同一套类型系统,没有“文本到 JSON 再到文本”的来回转换损耗。
二、第一个结构化命令:ls 与 ps 返回的是表
在 nushell 中,ls 不再打印人类可读的列表,而是返回一个带列(name、type、size、modified)的表格。你可以直接对它做筛选,而不必关心底层如何分隔字段:
ls | where size > 1mb | sort-by size --reverse | first 5
# 输出是一个表格,列包含 name / type / size / modified
ps | where cpu > 5.0 | sort-by cpu --reverse | select name cpu pid
# 直接按数值列筛选进程,无需 awk
更重要的是,表格是可组合的。你可以把 ls 的结果先筛选、再投影、再排序,每一步都看到清晰的列定义,而不必担心某个文件名里恰好含有空格或特殊字符就导致 awk 错位。这种“所见即所得”的结构,正是 nushell 提升命令行可靠性的关键。
三、管道传递的是行,不是字符串
3.1 where / select / sort-by 三件套
这三个命令几乎能覆盖八成的日常筛选需求:where 按条件过滤行,select 投影列,sort-by 按某列排序。它们都作用在表格上,因此类型安全——你不会不小心拿字符串去和数值比大小,也不会因为某行多一个空格就让整条管道崩掉。
理解这一点之后,很多原本需要写脚本才能完成的任务,现在一条管道就能解决。因为每一段管道的输入和输出都是带类型的行集合,你可以放心地把多个 where、select 串联起来,而不用担心中间的文本被意外截断或转义。这也是为什么 nushell 特别适合做“临时数据分析”——数据已经在手边,筛选随手就来。
3.2 把纯文本解析成表
面对非结构化的文本,nushell 提供 parse、split、lines 以及 from json/csv/xml 系列命令,先把它变成表,再进入结构化管道:
ls | to json | from json # 结构化 <-> JSON 无损互转
"2026-10-21 13:08 fail2ban" | parse "{date} {time} {svc}"
http get https://api.github.com/repos/nushell/nushell | get stargazers_count
四、实战:用 nushell 看清 Docker 占用
容器工程师每天都要和镜像、卷打交道。配合 Docker 容器化部署 的日常,用 nushell 可以一行看清谁在吃磁盘:
docker images --format '{{.Repository}} {{.Size}}' | lines | parse "{repo} {size}"
| sort-by size --reverse | first 10
docker ps --format '{{.Names}} {{.Status}}' | lines | parse "{name} {status}"
| where status =~ running
相比在 bash 里拼 docker images | awk,这里把输出先 parse 成带类型的列,再排序筛选,可读性与可维护性都更好。Redis 缓存实战 里我们讲过用命令行排查问题,nushell 让这类排查进一步结构化。
五、定义变量与可复用命令
nushell 用 let 声明变量(变量名前带 $),用 def 定义自己的命令,参数可标注类型,复用性远超传统的 shell 函数。变量默认不可变,若要在作用域内修改,应改用 mut 声明,这与很多函数式语言的约定一致,能减少意外的副作用。
let big = (ls | where size > 1mb)
def top-files [n:int] {
ls | where size > 0kb | sort-by size --reverse | first $n
}
top-files 5
六、和终端 / 编辑器工作流衔接
nushell 可以设为系统默认 shell,在 VS Code 终端 里直接享受结构化输出;配合 tldr 命令手册 与 GitHub Actions 做本地验证,能把“本地能跑”的排查逻辑平滑迁移到 CI。它在 macOS、Linux、Windows 上行为一致,对跨平台团队尤其友好。
七、nushell 与 bash/zsh 怎么选
结论先说在前面:nushell 更适合“分析式”的工作——临时看看数据、快速排查、把命令结果当表操作;而 bash/zsh 在编写需要长期维护的系统脚本、兼容老旧环境时依然不可替代。两者并非零和,很多人把 nushell 作为交互式终端、把 bash 留在脚本里。
| 维度 | nushell | bash / zsh |
| 管道数据 | 结构化表格(带类型) | 纯文本流 |
| 筛选方式 | where / select / sort-by | grep / awk / cut |
| 跨平台 | 原生一致 | 需适配(尤其 Windows) |
| 脚本生态 | 较新,逐步丰富 | 极其成熟 |
| 适用场景 | 数据分析式排查、可复用命令 | 系统脚本、兼容老环境 |
八、用配置文件定制启动环境
nushell 的启动配置放在 env.nu 与 config.nu 两个文件里,分别负责环境变量与交互体验。你可以把常用的别名、自定义命令、提示符样式都写进去,换台机器只要同步这两个文件就能复现整套工作流:
# config.nu 片段
alias ll = ls -l
$env.EDITOR = "code"
def my-ip [] { ipconfig getifaddr en0 }
这种“配置即代码”的方式,和用 chezmoi 管理 dotfiles 的思路一脉相承:把环境状态版本化,既方便回滚,也方便团队共享统一的排查命令集。
九、迁移时的常见坑
从 bash 迁移时最容易踩的坑,是下意识套用旧习惯。比如 nushell 里变量必须带 $ 且默认不可变,想修改要先 mut;再如字符串比较用 == 而非 bash 的 =,正则匹配用 =~。还有一点:nushell 的 if 是表达式,可以出现在管道中间直接参与计算。建议迁移阶段把老脚本一行行改写成结构化写法,而不是直接整段重写,避免一次引入太多新概念导致返工。
十、落地清单:今天就能开始的 5 件事
想把 nushell 真正用起来,不必一步到位替换 bash。建议按下面顺序渐进接入:
- 用包管理器装好 nushell(brew install nushell 或 apt 安装),先当作交互式增强终端。
- 把最常用的
ls | where、ps | where改写成结构化写法。 - 用
def把反复敲的长命令封装成自己的小命令。 - 用
parse处理日志与命令输出,替代脆弱的 awk。 - 在 VS Code 集成终端里把默认 shell 切到 nushell,日常即练。
nushell 不是要取代 bash,而是给你一把“把命令行当数据库用”的利器。当你下一次准备写一长串管道去抠文本字段时,不妨先问一句:这个输出,能不能先变成一张表?从今天起,把 ls、ps、docker 这些最常敲的命令改写成结构化写法,你会很快体会到“数据就在手边、筛选随手就来”的爽快。




