nushell
nushell 是一种新型Shell。它原生支持结构化和类型化数据,例如数组、表格、记录、数字/布尔类型等,并提供易于查询、过滤、排序、转换、转换以及以Shell风格工作流处理各种数据类型的语法和内置命令,同时支持以多种内置或用户定义的格式进行输入和输出。
安装
安装 nushell 包。然后您就可以启动 **nushell**。
$ nu
特性
结构化数据支持
**nushell** 的内置命令能够理解和输出复杂的数据类型。例如,ls 内置命令输出一个代表文件的项目数组,这些文件具有 name、size、type(file、dir、symlink 等)、modified 等属性。
此外,还提供了许多用于查询和操作数据的内置命令,数据以数据形式而非传统Shell中的文本形式处理,同时仍然保留Shell风格的工作流。例如,where 内置命令可以过滤数组或表格的内容。
> ls | where type == file | where size > 10mb
由于它通过“stdin”接收数据并从“stdout”输出数据,因此可以像上面那样连接多个过滤器。另一个例子:
> ls | where type == file | get size | math sum
get 内置命令可用于访问对象的属性。在此示例中,我们通过 stdin 向其提供一个对象数组,因此它会获取数组中每个元素的 size 属性,从而生成一个数字数组。最后,我们将该数组传递给 math sum,它会计算它们的总和。
输出
**nushell** 具有通用的输出功能。开箱即用,它提供了现代化的外观,带有颜色、ASCII艺术和详细的错误消息。
文本输出
默认情况下,ls(如前所述,它会生成结构化对象数组)等命令的输出会显示为带有编号行的彩色文本表格,其中每个文件是一行,每个属性是一列。示例:
/usr/lib> ls | where name =~ "alsa|pulse|pipewire" | first 10
╭───┬────────────────────────────┬─────────┬──────────┬──────────────╮ │ # │ name │ type │ size │ modified │ ├───┼────────────────────────────┼─────────┼──────────┼──────────────┤ │ 0 │ alsa-lib │ dir │ 4.1 KB │ 2 days ago │ │ 1 │ alsa-topology │ dir │ 4.1 KB │ 3 months ago │ │ 2 │ libdrumstick-alsa.so │ symlink │ 22 B │ 7 months ago │ │ 3 │ libdrumstick-alsa.so.2 │ symlink │ 26 B │ 7 months ago │ │ 4 │ libdrumstick-alsa.so.2.7.2 │ file │ 335.3 KB │ 7 months ago │ │ 5 │ libgvncpulse-1.0.so │ symlink │ 21 B │ 9 months ago │ │ 6 │ libgvncpulse-1.0.so.0 │ symlink │ 25 B │ 9 months ago │ │ 7 │ libgvncpulse-1.0.so.0.0.1 │ file │ 14.1 KB │ 9 months ago │ │ 8 │ libpipewire-0.3.so │ symlink │ 20 B │ 2 weeks ago │ │ 9 │ libpipewire-0.3.so.0 │ symlink │ 26 B │ 2 weeks ago │ ╰───┴────────────────────────────┴─────────┴──────────┴──────────────╯
行为取决于配置。
> $env.config.hooks.display_output
if (term size).columns >= 100 { table -e } else { table }
数据格式输出
数据也可以以各种数据格式输出,包括 JSON、YAML、TOML、HTML、XML、SQL、CSV、Markdown 表格等。用户还可以定义自己的自定义查看器来支持任意数据类型。
要以给定格式输出数据,只需将数据管道传输到 to FORMAT 即可。
/usr/lib> ls | where name =~ alsa | first 3 | to yaml
- name: alsa-lib type: dir size: 4096 modified: 2023-05-03 16:04:35.544273606 - name: alsa-topology type: dir size: 4096 modified: 2023-01-13 19:29:45.179245376 - name: libdrumstick-alsa.so type: symlink size: 22 modified: 2022-10-02 13:28:57
要将命令的输出保存到文件,请将其管道传输到 save 内置命令。
> ls | to json | save my-file.json
如果输出文件已存在,save 将拒绝覆盖它。您可以使用 -f 开关强制覆盖文件。
请注意,**nushell** 默认生成美化打印的 JSON。要输出非美化打印的 JSON,请使用 to json --raw。
有关支持的格式列表,请参阅 to --help。
错误输出
**nushell** 会打印彩色化和详细的错误消息,这些消息会精确定位错误的具体来源并提出解决方案。示例错误消息:
> ls -a --never-gonna-give-you-up /tmp
Error: nu::parser::unknown_flag
× The `ls` command doesn't have flag `never-gonna-give-you-up`.
╭─[entry #24:1:1]
1 │ ls -a --never-gonna-give-you-up /tmp
· ────────────┬────────────
· ╰── unknown flag
╰────
help: Available flags: --help(-h), --all(-a), --long(-l),
--short-names(-s), --full-paths(-f), --du(-d), --directory(-D),
--mime-type(-m). Use `--help` for more information.
输入
数据文件输入
**nushell** 原生支持读取多种格式的数据,包括 JSON、YAML、TOML、SQL、HTML/XML 等,允许用户对其从任何文件格式读取的数据利用其强大的数据查询和操作能力。用户还可以通过添加插件来支持新格式。
数据使用 open 内置命令从文件中读取。例如,假设有以下文件:
movies.yaml
- movie: Matrix genre: Action - movie: Lord of the Rings genre: [Action, Fantasy] - movie: Independence Day genre: [Action, Sci-Fi]
使用 open 会产生以下结果:
open movies.yaml
╭───┬───────────────────┬─────────────────╮ │ # │ movie │ genre │ ├───┼───────────────────┼─────────────────┤ │ 0 │ Matrix │ Action │ │ 1 │ Lord of the Rings │ ╭───┬─────────╮ │ │ │ │ │ 0 │ Action │ │ │ │ │ │ 1 │ Fantasy │ │ │ │ │ ╰───┴─────────╯ │ │ 1 │ Independence Day │ ╭───┬─────────╮ │ │ │ │ │ 0 │ Action │ │ │ │ │ │ 1 │ Sci-Fi │ │ │ │ │ ╰───┴─────────╯ │ ╰───┴───────────────────┴─────────────────╯
外部程序输入
对于通常以纯文本形式生成输出的外部程序,**nushell** 提供了解析其输出并将其转换为结构化数据类型的能力,以便用户即使对普通程序生成的任意输出也能利用 **nushell** 全面的原生数据处理功能。
使用正则表达式解析
可以使用 parse 内置命令轻松解析外部程序的输出。一种典型的做法是使用 -r 开关,它告诉 parse 使用 正则表达式 从输入文本的每一行中提取字段。例如,要解析 pacman 的 -Si 命令的输出,可以这样做:
> pacman -Si rclone | parse -r '(?P<name>.*\w) +: (?P<value>.+)' ╭────┬────────────────┬─────────────────────────────────────────────────╮ │ # │ name │ value │ ├────┼────────────────┼─────────────────────────────────────────────────┤ │ 0 │ Repository │ extra │ │ 1 │ Name │ rclone │ │ 2 │ Version │ 1.62.2-1 │ │ 3 │ Description │ Sync files to and from Google Drive, S3, Swift, │ │ │ │ Cloudfiles, Dropbox and Google Cloud Storage │ │ 4 │ Architecture │ x86_64 │ │ 5 │ URL │ https://rclone.org/ │ │ 6 │ Licenses │ MIT │ │ 7 │ Groups │ None │ │ 8 │ Provides │ None │ │ 9 │ Depends On │ glibc │ │ 10 │ Optional Deps │ fuse2: for rclone mount │ │ 11 │ Conflicts With │ None │ │ 12 │ Replaces │ None │ │ 13 │ Download Size │ 18.12 MiB │ │ 14 │ Installed Size │ 75.93 MiB │ │ 15 │ Packager │ Morten Linderud <foxboron@archlinux.org> │ │ 16 │ Build Date │ Sun 02 Apr 2023 14:09:44 EEST │ │ 17 │ Validated By │ MD5 Sum SHA-256 Sum Signature │ ╰────┴────────────────┴─────────────────────────────────────────────────╯
**nushell** 使用 Perl 风格的正则表达式语法,由(Rust 编程语言的)Regex crate 提供。语法在crate 的文档中有描述。
使用模板字符串解析
另一种不需要正则表达式知识的方法是省略 -r 开关,并为 parse 提供一个模板字符串。但是,根据具体情况,这可能需要额外的步骤来预处理和后处理结果。例如:
> pacman -Si just | lines | parse '{field} : {value}' | str trim
在这里,我们完成了与上面相同的任务,但有三个不同之处。除了使用模板字符串而不是正则表达式(即不带 -r 开关)之外,第一个值得注意的区别是,当 parse 接收到模板字符串时,它会处理其全部输入,而不是逐行处理。因此,为了逐行解析输入,我们必须先使用 lines 内置命令将其拆分为数组。
第二个区别是模板字符串不会自动修剪多余的空格,这导致匹配的字段包含它们周围的所有额外空格,因此我们必须使用 str trim 对输出进行后处理,它会方便地作用于提供数组中所有项的所有字段。
数据操作
转换
其 open 和 save 内置命令的结合使其能够轻松地用于在任何支持的格式之间转换数据文件。例如:
然后可以自由地通过管道将其传输到其他命令来操作或转换数据。例如:
> open movies.yaml | first 2 | to json --raw
[{"movie": "Matrix","genre": "Action"},{"movie": "Lord of the Rings","genre":["Action","Fantasy"]}]
> open movies.yaml | first 2 | to json --raw | save movies.json
> cat movies.json
(same output as above)
与传统Shell的比较
**nushell** 不是 POSIX Shell,并且在语法、支持的内置命令、内置命令的工作方式、它们接受的命令行选项、它们消耗和产生的数据类型等方面,与传统/ POSIX 兼容的 Shell 有显著区别。
语法
不能像其他 Shell 那样使用 > 将输出重定向到文件(因为 > 具有大于号的含义)。
所以,而不是
ls > file.txt
这是一个错误,请改用,例如:
ls | get name | save file.txt
Nushell 的重定向语法是,例如 out>(缩写为 o>)、err>、e+o>。如果使用的是系统的 ls 命令而不是内部命令,可以在前面的示例中直接使用,方法是在前面加上 ^。
^ls o> file.txt
参见
- **nushell** 项目主页.
- Nushell 入门指南,详细介绍了其功能和各个方面。
- Nushell 命令参考
- Nushell 菜谱,包含有关如何在 **nushell** 中执行各种类别任务的示例。