ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

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

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 处理器中的全部布尔操作符二元操作符or、and一元操作符not作用于数组的any、all以及带条件表达式的any_c、all_c。你将掌握每个操作符的语法、真值判定规则、与select组合过滤节点的典型用法并通过源码实现理解短路求值、空数组语义等底层原理最终能够在日常数据处理中写出准确、高效的过滤与判断表达式。布尔操作符一览操作符参数个数说明or2左右两侧取其一为真即为真真值表同逻辑或and2左右两侧同时为真才为真真值表同逻辑与not1前置管道将布尔值取反true 变 false、false 变 trueany0数组序列中存在任一true元素则返回trueall0数组序列中所有元素均为true才返回trueany_c(condition)1条件表达式对每个元素应用条件表达式任一元素满足即返回trueall_c(condition)1条件表达式对每个元素应用条件表达式所有元素满足才返回true其中or、and是二元操作符在 operation.go 中定义参数个数为 2not、any、all定义见 operation.go 与 operation.goany_c、all_c各接收 1 个条件表达式参数。词法层面这些关键字通过 lexer_participle.go 与 lexer_participle.go 中的simpleOp注册。从源码结构可以推断or/and的优先级为 20低于not、any、all、any_c、all_c的优先级 50因此在组合表达式中布尔运算会先完成高优先级部分的求值再与比较操作符如协同工作。or操作符两侧任一为真即为真or接收两个参数并返回布尔结果。最直接的验证方式是利用--null-input标志不读取任何输入文件直接对表达式求值yq --null-input true or false输出trueor的实现位于 operator_booleans.go它通过crossFunctionWithPrefs装配以下行为CalcWhenEmpty: true当左侧表达式无匹配节点如.a在文档中不存在时仍然参与计算此时右侧结果直接决定返回值。测试用例b: hi文档上执行.a or .c得到false正是这一行为见 operator_booleans_test.goLhsResultValue: returnLHSWhen(true)短路求值——只要左侧为真就直接返回true不再计算右侧。测试用例true or test(3)输出true且不会执行test(3)见 operator_booleans_test.go避免了不必要的求值与副作用。and操作符两侧同为真才为真yq --null-input true and false输出falseand的实现见 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输出falseyq --null-input false | not输出truenot的实现遍历所有匹配节点并逐一取反见 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四段输出依次为false、false、false、false、true对应测试见 operator_booleans_test.go。值得注意的是yq 在判定布尔标量时遵循 YAML 1.1/1.2 兼容的布尔词集合yes、on、y均被视为真isTruthyNode中strings.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输出trueallOperator见 operator_booleans.go同样限定输入必须是数组它调用findBoolean(false, ...)只要遍历到任一非真元素即提前返回false遍历完仍未发现假值则整体为true——这正是空数组返回true的原因。any_c与all_c带条件表达式的数组判定any_c(condition)与all_c(condition)是any/all的增强版它们接收一个条件表达式对数组中的每个元素分别求值再判断整体结果。给定 sample.ymla: - rad - awesome b: - meh - whatever执行yq .[] | any_c(. awesome) sample.yml输出a: true b: false再给定 sample.ymla: - rad - awesome b: - meh - 12执行yq .[] | all_c(tag !!str) sample.yml输出a: true b: false第二个例子中a的两个元素rad、awesome的tag都是!!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证明yes、no被当作字符串处理。这意味着如果业务数据依赖yes/no表达布尔语义需要先将其转换为真正的布尔值例如配合 yes比较或转换为字符串后再判定否则布尔操作符按isTruthyNode的规则会把非空字符串一律视为真产生与直觉相悖的结果。源码脉络从词法到求值的完整链路布尔操作符的完整调用链可归纳为词法解析lexer_participle.go 中simpleOp将or、and、not、any、all、any_c、all_c识别为对应操作符类型操作符定义operation.go 与 operation.go 声明参数个数、优先级并绑定处理函数orOperator、andOperator、notOperator、anyOperator、allOperator求值实现operator_booleans.go 实现全部求值逻辑其中真值判定收敛于isTruthyNode二元运算收敛于crossFunctionWithPrefs见 operators.go数组判定收敛于findBoolean测试验证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 独有的真值判定规则仅null与false为假、非空字符串与数字均为真以及 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),仅供参考
返回列表