news 2026/9/12 11:38:53

Nushell 如何用 from nuon 和 to nuon 读写带注释、尾随逗号与表格形式的 NUON 文件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Nushell 如何用 from nuon 和 to nuon 读写带注释、尾随逗号与表格形式的 NUON 文件

Nushell 如何用 from nuon 和 to nuon 读写带注释、尾随逗号与表格形式的 NUON 文件

【免费下载链接】nushellA new type of shell项目地址: https://gitcode.com/GitHub_Trending/nu/nushell

当数据文件由人手工编写或审阅时,JSON 往往显得啰嗦:每行都要重复键名,不能写注释,尾随逗号还会直接报错。Nushell 内置的 NUON 格式(Nushell Object Notation)解决了这些问题。from nuon把 NUON 文本反序列化为结构化数据,to nuon把 Nushell 值序列化为 NUON 文本,两个命令都属于 Formats 类别,随 Nushell 发布即可使用。本文按仓库中 crates/nuon/README.md、正式规范 和 命令实现 中的真实示例,走一遍“读入带注释、尾随逗号与表格形式的 NUON → 改造成想要的输出风格 → 验证往返一致”的完整路径。

前提:NUON 是 JSON 的超集,外加表格形式

按 crates/nuon/README.md 的定义,NUON 在 JSON 基础上增加了:

  • 允许尾随逗号,列表中的逗号本身也是可选的(用空白分隔也可以);
  • 键和不包含空格、特殊字符的字符串可以不带引号;
  • 允许#注释——但from nuon不会保留注释;
  • 数字支持十六进制、八进制、二进制,可带_分隔符,可以以+或孤立的.开头;
  • 2min1kb2000-01-01T00:00:00+00:00这类 duration、filesize、datetime 是字面量,0x[be ef]$.a.b1..5分别是 binary、cell-path 和 range;
  • 一组结构一致的 record 列表可以写成表格形式,列名只写一次,而不是每行重复。

同一段数据两种写法的对照(示例取自 README):

{ "name": "Some One", "birth": "1970-01-01", "stats": [ 2544729499973429198, 687051042647753531, 6702443901704799912 ] }
{ name: "Some One", # the name of the person birth: "1970-01-01", # their date of birth stats: [ # some dummy "stats" about them 2544729499973429198, 687051042647753531, 6702443901704799912, # note the trailing comma here... ], # and here } # wait, are these comments in a JSON-like document?!?!

NUON 文件就是 UTF-8 文本文件:规范要求输入必须是合法的 UTF-8,开头的 BOM 会被剥掉恰好一个。所有读写都是通过管道把文本交给这两个命令完成的。

用 from nuon 读入带注释与尾随逗号的文档

from nuon的签名是字符串输入、任意类型输出(from nuon 实现),命令文档给出的可直接执行示例:

'{ a:1 }' | from nuon # 结果:record { a: 1 } '{ a:1, b: [1, 2] }' | from nuon # 结果:record { a: 1, b: [1 2] } '{a:1,b:[1,2]}' | from nuon # 结果:record { a: 1, b: [1 2] }

带注释和尾随逗号的文档能直接读入(示例输出取自正式规范,规范约定其中的nushell代码块是“带真实输出的命令”):

'[1, 2, 3,]' | from nuon | to json -r # => [1,2,3]

注意#成为注释是有条件的:只在 token 边界处(输入开头、空白、或, : [ ] { } ;之后)才算注释符,紧贴在前一个词后面时就是普通字符。这两条对照来自规范,判断你的文档里#到底起了什么作用:

"[a#b]" | from nuon | to json -r # => ["a#b"] "[a, # note\n b]" | from nuon | to json -r # => ["a","b"]

读入后注释被丢弃,这是 README 明确说明的行为:允许注释,但from_nuon不保留它们。

表格形式:列名只写一次

表格形式的语法是[ 表头; 行1 行2 ... ],表头和每一行都是列表,行单元格按位置对应表头列名。解码后它就是一组 record 的列表,与逐行写 record 没有区别:

'[[a b]; [1 2] [3 4]]' | from nuon | to json -r # => [{"a":1,"b":2},{"a":3,"b":4}]

README 里用 3 行 4 列的例子展示了压缩效果:同样的数据在 JSON 里要重复每个键,NUON 表格形式把 20 行压成 6 行,四个列名只写了一次。

写表格文件时有几条硬规则,违规会直接报错而不是静默出错(以下均为规范中的文档示例):

# 表头必须是字符串 '[[a 1]; [1 2]]' | from nuon # => error # 行长度必须与表头一致 '[[a b]; [1]]' | from nuon # => error # 列名不能重复 '[[a b a]; [1 2 3]]' | from nuon # => error: column_defined_twice

另外,“有表头但没有数据行”在表格形式下无法表达,空表只能写[]

用 to nuon 写出 NUON,并控制输出风格

to nuon接受任意输入、输出字符串,默认是紧凑的单行输出。命令文档 中经过测试的示例:

[1 2 3] | to nuon # 结果:[1, 2, 3] [1 2 3] | to nuon --indent 2 # 结果: # [ # 1, # 2, # 3 # ] {date: 2000-01-01, data: [1 [2 3] 4.56]} | to nuon --indent 2 # 结果: # { # date: 2000-01-01T00:00:00+00:00, # data: [ # 1, # [ # 2, # 3 # ], # 4.56 # ] # }

注意 date 值被写成完整的 RFC 3339 形式:writer 对 datetime 总是输出完整形式(规范示例:{date: 2000-01-01} | to nuon # => {date: 2000-01-01T00:00:00+00:00})。

to nuon的全部开关及默认值(规范给出的表,除特别说明外默认全部关闭):

开关短参数默认作用
--raw-r去掉所有空白
--indent N-i每项一行,每层缩进 N 个空格
--tabs N-t每项一行,每层缩进 N 个制表符
--pretty-p等价于--indent 2
--list-of-records-l不用表格形式,逐行输出 record
--no-commas-c用空白代替逗号分隔
--raw-strings-R把含引号或反斜杠的字符串写成r#'...'#
--serialize-s把无法反序列化回来的类型序列化为字符串

开关冲突时的优先级规则也是规范明确写死的,判断输出形态时按这个顺序:

  • --raw压过--indent--tabs--pretty[[a b]; [1 2]] | to nuon --pretty --raw结果是[[a,b];[1,2]]
  • --tabs压过--indent
  • --indent 0--tabs 0等价于--raw
  • --raw不压过--list-of-records--raw-strings,这两者可以与它组合:[[a b]; [1 2]] | to nuon --raw --list-of-records结果是[{a:1,b:2}]
  • --raw--no-commas互斥:前者删空白、后者用空白当分隔符,同时用会没有分隔符,[1 2 3]会被读回成整数123

几个常用分支的输出(均为命令文档或规范中的示例):

[[a, b]; [1, 2], [3, 4]] | to nuon --list-of-records # => [{a: 1, b: 2}, {a: 3, b: 4}] [1 2 3] | to nuon --no-commas # => [1 2 3] {a: 1, b: 2} | to nuon --no-commas # => {a: 1 b: 2} 'helloworld'.into | to nuon --raw # 文档示例:--raw 覆盖其它缩进选项 [1 2 3] | to nuon --indent 2 --raw # => [1,2,3] 'hello "world"' | to nuon --raw-strings # => r#'hello "world"'# [[name, age]; [Alice, 30], [Bob, 25]] | to nuon --pretty # => [ # [name, age]; # [Alice, 30], # [Bob, 25] # ]

--pretty会同时对齐表格列,--indent走的是同一条代码路径,所以--indent N也会对齐列。--list-of-records下即使带缩进,每个 record 仍会内联在一行里。

何时自动使用表格形式,何时不会

to nuon不是无条件把列表写成表格。规范给出的判定条件:列表非空、每个元素都是 record、record 至少有一个键、且所有 record 键相同且顺序相同,才会用表格形式;键顺序不同就会被判成普通列表:

[{a: 1, b: 2}, {b: 3, a: 4}] | to nuon # => [{a: 1, b: 2}, {b: 3, a: 4}] [{}, {}] | to nuon # => [{}, {}]

想强制不用表格形式时加--list-of-records,它会无条件关闭表格语法。

验证:往返一致性与输出类型

最直接的验证是读写往返。规范值模型一节给出的例子说明 binary、cell-path、range 三类值能完整往返(即from nuon读得回to nuon写出的所有内容):

"[0x[be ef], $.a.b, 1..5]" | from nuon | to nuon # => [0x[BEEF], $.a.b, 1..5]

也可以用metadata检查to nuon产物携带的内容类型(该断言来自 to nuon 命令测试):

{a: 1 b: 2} | to nuon | metadata | get content_type # 结果:"application/x-nuon"

读入失败时的报错信息来自 from nuon 实现 的错误分支,可按消息文本定位原因:

  • error when loading nuon text/could not load nuon text——外层包装;
  • error when parsing nuon text——语法解析失败;
  • table has mismatched columns——表格行与表头长度不一致;
  • only strings can be keys——表头/键不是字符串;
  • column_defined_twice(即规范中写的error: column_defined_twice)——record 键或表格列名重复;
  • excess values when loading——输入里不止一个顶层值;
  • detected a pipeline in nuon file——输入里出现了管道;
  • variables not supported in nuoncalls not supported in nuon等——NUON 只是数据格式,变量、命令调用、闭包、子表达式都不允许。

限制与边界

  • 注释只在读入时存在from nuon不保留注释,to nuon也不会生成注释。带注释的文件经过一次往返后注释会消失。

  • writer 的引号规则:字符串只有在满足“非空、不含强制加引号字符集、不含 Unicode 空白、不含任何十进制数字(类别Nd)、读回来仍是字符串”时才不加引号。所以a1会被加引号而a-b不会:

    ["a1" "0x" abc "x-1" "a-b" "a_b" "1s" "E5" "3/4"] | to nuon # => ["a1", "0x", abc, "x-1", a-b, a_b, "1s", "E5", "3/4"]

    规范特别警告:0x0o80b2这类普通字符串如果裸写,reader 会提交到进制字面量解析然后报错,即产生“自己都打不开的文件”——writer 的加引号逻辑就是为了避免这种情况。

  • duration 和 filesize 的写回形式:writer 对 duration 一律输出ns[1sec] | to nuon # => [1000000000ns]),filesize 一律输出b[1kb] | to nuon # => [1000b]),读入时的2min1kb形式只在文件里存在。

  • 裸词不能单独成文"abc" | from nuon是错误,裸词只能在列表、record 等结构内部使用;顶层单独一个字符串会被 writer 加引号("hi" | to nuon # => "hi"["hi"] | to nuon # => [hi])。

  • 不能序列化的类型:closure 默认报错,提示use --serialize to serialize as a string;custom value 直接报custom values are currently not nuon-compatible。按规范,--serialize实际只对 closure 和 block 生效,binary、cell-path、range 无论是否加该开关都原生写出,glob 无论如何都会变成普通字符串。

完整的语法定义、单位后缀表和逐条的合规检查清单,见 crates/nuon/spec/nuon_formal_specification.md;规范中还维护了 bugs_to_fix.md 追踪当前实现与规范仍不一致的地方,读入行为与上述规则有出入时可以对照该文件。

【免费下载链接】nushellA new type of shell项目地址: https://gitcode.com/GitHub_Trending/nu/nushell

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/12 11:38:32

Kali Linux 2026渗透测试指令速查与实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 11:37:13

C++字符串反转:双指针法与STL实现对比

1. 反转字符串的核心思路与实现字符串反转是算法学习中最基础的练习之一,但恰恰是这种基础操作,能帮助我们理解计算机处理数据的底层逻辑。在C中,字符串本质上是一个字符数组,这意味着我们可以通过指针或索引直接访问和修改其中的…

作者头像 李华
网站建设 2026/9/12 11:32:27

DeepSeek Harness本地模型服务化实战指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/12 11:29:14

OpenAI技术栈解析:从ChatGPT到GPT-5.4的模型选型指南

1. OpenAI技术栈全景解析:从ChatGPT到GPT-5.4的技术脉络 作为深度参与AI工具落地的技术从业者,我经常需要向开发团队解释OpenAI旗下各种模型的关系。2023年Q2的技术报告显示,超过67%的企业级AI应用都涉及OpenAI技术栈的选型决策。但面对ChatG…

作者头像 李华