news 2026/9/14 5:39:28

yq 布尔操作符完全指南:or / and / not / any / all / any_c / all_c 与 select 过滤实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
yq 布尔操作符完全指南:or / and / not / any / all / any_c / all_c 与 select 过滤实战

yq 布尔操作符完全指南:or / and / not / any / all / any_c / all_c 与 select 过滤实战

【免费下载链接】yqyq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor项目地址: https://gitcode.com/GitHub_Trending/yq/yq

导读

本文系统讲解 yq(一个可移植的命令行 YAML、JSON、XML、CSV、TOML、HCL 与 properties 处理器)中的全部布尔操作符:二元操作符orand,一元操作符not,作用于数组的anyall,以及带条件表达式的any_call_c。你将掌握每个操作符的语法、真值判定规则、与select组合过滤节点的典型用法,并通过源码实现理解短路求值、空数组语义等底层原理,最终能够在日常数据处理中写出准确、高效的过滤与判断表达式。

布尔操作符一览

操作符参数个数说明
or2左右两侧取其一为真即为真(真值表同逻辑或)
and2左右两侧同时为真才为真(真值表同逻辑与)
not1(前置管道)将布尔值取反,true 变 false、false 变 true
any0数组序列中存在任一true元素则返回true
all0数组序列中所有元素均为true才返回true
any_c(condition)1(条件表达式)对每个元素应用条件表达式,任一元素满足即返回true
all_c(condition)1(条件表达式)对每个元素应用条件表达式,所有元素满足才返回true

其中orand是二元操作符,在 operation.go 中定义,参数个数为 2;notanyall定义见 operation.go 与 operation.go;any_call_c各接收 1 个条件表达式参数。词法层面,这些关键字通过 lexer_participle.go 与 lexer_participle.go 中的simpleOp注册。

从源码结构可以推断:or/and的优先级为 20,低于notanyallany_call_c的优先级 50,因此在组合表达式中布尔运算会先完成高优先级部分的求值,再与比较操作符(如==)协同工作。

or操作符:两侧任一为真即为真

or接收两个参数并返回布尔结果。最直接的验证方式是利用--null-input标志,不读取任何输入文件,直接对表达式求值:

yq --null-input 'true or false'

输出:

true

or的实现位于 operator_booleans.go,它通过crossFunctionWithPrefs装配以下行为:

  • CalcWhenEmpty: true:当左侧表达式无匹配节点(如.a在文档中不存在)时,仍然参与计算,此时右侧结果直接决定返回值。测试用例b: hi文档上执行.a or .c得到false正是这一行为(见 operator_booleans_test.go);
  • LhsResultValue: returnLHSWhen(true)短路求值——只要左侧为真,就直接返回true,不再计算右侧。测试用例true or test(3)输出true且不会执行test(3)(见 operator_booleans_test.go),避免了不必要的求值与副作用。

and操作符:两侧同为真才为真

yq --null-input 'true and false'

输出:

false

and的实现见 operator_booleans.go,同样使用CalcWhenEmpty: true,但LhsResultValue换成returnLHSWhen(false)只要左侧为假,立即返回false。对应测试用例false and test(3)输出false(见 operator_booleans_test.go)。

两者共享的底层框架是crossFunctionWithPrefs(见 operators.go)与resultsForRHS(见 operators.go):先求值左侧表达式,若左侧满足短路条件则跳过右侧求值,否则逐一求值右侧并合并结果。这套机制保证了布尔运算既能正确处理"左值缺失"的场景,又能像主流编程语言一样短路。

not操作符与 yq 的真值判定规则

not翻转布尔值:

yq --null-input 'true | not'

输出:

false
yq --null-input 'false | not'

输出:

true

not的实现遍历所有匹配节点并逐一取反(见 operator_booleans.go),而"何为真"由核心函数isTruthyNode决定(见 operator_booleans.go),规则如下:

节点类型判定结果
null!!null标签)false(唯一被视为假的非布尔类型)
标量且标签为!!bool值等于y/yes/on/true(不区分大小写)时为真,否则为假
其他一切节点(字符串、数字、映射、数组等)true

这意味着字符串、数字乃至0都被视为"真",只有null和显式的false布尔值才是"假"。文档与测试用例完整覆盖了这些边界情况:

yq --null-input '"cat" | not' # 字符串视为真,not 后为 false yq --null-input '"" | not' # 空字符串同样视为真,not 后为 false yq --null-input '1 | not' # 数字视为真,not 后为 false yq --null-input '0 | not' # 0 也视为真,not 后为 false yq --null-input '~ | not' # null 视为假,not 后为 true

四段输出依次为falsefalsefalsefalsetrue(对应测试见 operator_booleans_test.go)。值得注意的是,yq 在判定布尔标量时遵循 YAML 1.1/1.2 兼容的布尔词集合,yesony均被视为真(isTruthyNodestrings.EqualFold不区分大小写)。

any:数组中是否存在真值

any作用于数组序列,只要存在任意一个true值即返回true

给定 sample.yml:

- false - true

执行:

yq 'any' sample.yml

输出:

true

对于空数组:

[]

执行同样的yq 'any' sample.yml,输出:

false

从源码看,any的实现为anyOperator(见 operator_booleans.go):它要求当前匹配节点必须是序列(SequenceNode),否则直接报错any only supports arrays;随后调用findBoolean(true, ...)遍历元素,一旦发现真值即返回true,空数组自然得到false

all:数组是否全为真值

all要求数组中的所有元素都为true才返回true

给定 sample.yml:

- true - true

执行:

yq 'all' sample.yml

输出:

true

any相反,all对空数组返回true(数学上的"空真"语义):

[]

执行yq 'all' sample.yml,输出:

true

allOperator(见 operator_booleans.go)同样限定输入必须是数组,它调用findBoolean(false, ...):只要遍历到任一非真元素即提前返回false,遍历完仍未发现假值则整体为true——这正是空数组返回true的原因。

any_call_c:带条件表达式的数组判定

any_c(condition)all_c(condition)any/all的增强版:它们接收一个条件表达式,对数组中的每个元素分别求值,再判断整体结果。

给定 sample.yml:

a: - rad - awesome b: - meh - whatever

执行:

yq '.[] |= any_c(. == "awesome")' sample.yml

输出:

a: true b: false

再给定 sample.yml:

a: - rad - awesome b: - meh - 12

执行:

yq '.[] |= all_c(tag == "!!str")' sample.yml

输出:

a: true b: false

第二个例子中,a的两个元素radawesometag都是!!str(字符串),因此all_c为真;而b中混入了数字12tag!!int),整体判定为假。

其底层机制在findBoolean(见 operator_booleans.go):当条件表达式存在时,先对每个数组元素调用GetMatchingNodes求值条件,取首个匹配结果参与真值判断;若某元素对条件无匹配结果,则该元素被跳过。需要留意的是,官方文档明确指出:在 jq 中可以直接把条件传给any/all,而 yq 目前尚不支持这种写法,必须显式使用any_c/all_c

any_c/all_c的条件结果同样可以绑定到变量复用,测试用例any_c(.name == "harry") as $c | $c返回false(见 operator_booleans_test.go),说明其返回值与普通表达式一致,可参与后续管道处理。

select组合:按布尔条件过滤节点

布尔操作符最常见的实战场景是与select操作符组合,过滤出满足复合条件的节点。

给定 sample.yml:

- a: bird b: dog - a: frog b: bird - a: cat b: fly

执行:

yq '[.[] | select(.a == "cat" or .b == "dog")]' sample.yml

输出:

- a: bird b: dog - a: cat b: fly

这里.[]展开数组的每个元素,select(...)依据括号内的布尔表达式决定是否保留节点,外层[...]将过滤结果重新收集为数组。or连接的两个==比较(equals/not equals 操作符,见 equals.md)正是布尔操作符与比较操作符协作的典型形态。select的详细用法可参考 select.md,而>=<等比较操作符见 compare.md。

反向过滤也常用not配合:测试用例select((.a and .b) | not)(见 operator_booleans_test.go)展示了"当某复合条件不满足时保留节点"的写法,等价于过滤掉同时满足.a.b的节点。

常见陷阱:YAML 1.2 中yes/no是字符串

在处理布尔数据时,一个容易踩坑的点是:根据 YAML 1.2 规范(见规范 10.2.1.2 Boolean 章节),yes/no不再被解析为布尔值,而是普通字符串。

给定 sample.yml:

- yes - no

执行:

yq '.[] | tag' sample.yml

输出:

!!str !!str

两个元素的tag都是!!str,证明yesno被当作字符串处理。这意味着如果业务数据依赖yes/no表达布尔语义,需要先将其转换为真正的布尔值(例如配合== "yes"比较或转换为字符串后再判定),否则布尔操作符按isTruthyNode的规则会把非空字符串一律视为真,产生与直觉相悖的结果。

源码脉络:从词法到求值的完整链路

布尔操作符的完整调用链可归纳为:

  1. 词法解析:lexer_participle.go 中simpleOporandnotanyallany_call_c识别为对应操作符类型;
  2. 操作符定义:operation.go 与 operation.go 声明参数个数、优先级并绑定处理函数(orOperatorandOperatornotOperatoranyOperatorallOperator);
  3. 求值实现:operator_booleans.go 实现全部求值逻辑,其中真值判定收敛于isTruthyNode,二元运算收敛于crossFunctionWithPrefs(见 operators.go),数组判定收敛于findBoolean
  4. 测试验证:operator_booleans_test.go 通过booleanOperatorScenarios表驱动测试覆盖了本文全部示例,包括短路求值、空数组语义、缺失字段处理、真值边界(字符串、数字、0、null)等 30 余个场景,运行go test ./pkg/yqlib/ -run TestBooleanOperatorScenarios即可复现验证。

小结

yq 的布尔操作符家族虽小,却覆盖了过滤场景的绝大多数需求:or/and负责复合条件组合并支持短路求值,not负责取反,any/all处理纯布尔数组,any_c/all_c以条件表达式驱动数组判定,再配合select即可完成任意复杂度的节点筛选。理解 yq 独有的真值判定规则(仅nullfalse为假、非空字符串与数字均为真)以及 YAML 1.2 的yes/no字符串语义,是写出无 bug 过滤表达式的关键前提。

【免费下载链接】yqyq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor项目地址: https://gitcode.com/GitHub_Trending/yq/yq

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

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

PDF-XChange Editor Plus v9.0.353安装与命令行批处理实战

简介&#xff1a;PDF-XChange Editor Plus 是一款以高速打开与轻量体积著称的 PDF 编辑及阅读工具&#xff0c;面向需要频繁处理 PDF 文档的办公人群与专业用户。该版本基于 x64 平台打包&#xff0c;支持创建、查看、编辑、注释、审阅、添加水印、签名保护、格式转换以及 OCR …

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

SEO优化全攻略:从技术到内容的搜索引擎排名提升

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

作者头像 李华
网站建设 2026/9/14 5:36:10

Superpowers技能包实测:让AI编程助手从对话工具变成工程协作者

最近在折腾AI编程工具的时候&#xff0c;我频繁看到一个词从不同渠道冒出来&#xff1a;superpowers。先是有人给Codex CLI装了一堆skill&#xff0c;接着WorkBuddy里也有人问怎么挂载&#xff0c;后来Trae那边也冒出“superpowers skill”的安装教程。我一开始以为又是什么花里…

作者头像 李华
网站建设 2026/9/14 5:35:07

Cursor Rules+Skills:构建可复用的AI编码操作系统

1. 项目概述&#xff1a;这不是又一个AI编程插件教程&#xff0c;而是一套可落地、可传承的“人机协同编码操作系统”你有没有过这种体验&#xff1a;写一段React组件逻辑&#xff0c;AI生成的代码看起来很美&#xff0c;但一跑就报错&#xff1b;调试时反复让AI解释某段TypeSc…

作者头像 李华