资讯动态

yq filter 操作符完全指南:用布尔表达式筛选数组与映射值

发布时间:2026/9/14 17:30:32 来源:尧图企业网站定制
yq filter 操作符完全指南用布尔表达式筛选数组与映射值【免费下载链接】yqyq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor项目地址: https://gitcode.com/GitHub_Trending/yq/yqfilter是 yq 中用于按表达式筛选数组或映射值的核心操作符功能上等价于map(select(exp))的组合写法。本文以 filter.md 为主线结合 operator_filter.go 等源码实现与 operator_filter_test.go 测试用例完整讲解filter的语法、数组/映射两种典型用法、边界行为以及与select操作符的差异帮助你写出更简洁、可读性更高的 yq 表达式。一句话理解 filterFilters an array (or map values) by the expression given. Equivalent to doingmap(select(exp)).filter(exp)接收一个布尔表达式exp对输入数组或映射的值列表逐项求值表达式为真的元素被保留为假的元素被丢弃。最终输出仍然是一个序列sequence而不是打散后的单个元素——这是它与select最直观的区别。过滤数组给定sample.yml- 1 - 2 - 3执行yq filter(. 3) sample.yml输出- 1 - 2表达式filter(. 3)中.依次代表数组中的每一个元素1、2、3 3是比较操作符返回布尔值结果仅保留满足条件的1和2并重新聚合为序列[1, 2]。该行为在源码测试 operator_filter_test.go 中有完全一致的验证{ description: Filter array, document: [1,2,3], expression: filter(. 3), expected: []string{ D0, P[], (!!seq)::[1, 2]\n, }, },注意期望值中的(!!seq)——它证明filter的输出保留了序列形态且文档路径P[]表明结果是一个新的根级集合而非逐个元素输出。过滤映射的值filter同样适用于映射类型此时它会对映射的值逐项求值命中的值收集为序列输出。给定sample.ymlc: things: cool frog: yes d: things: hot frog: false执行yq filter(.things cool) sample.yml输出- things: cool frog: yes这里映射c与d的值分别是两个子映射filter(.things cool)对它们逐一判断.things字段是否等于cool仅c的值通过筛选最终以单元素序列输出。对应测试见 operator_filter_test.go{ description: Filter map values, document: {c: {things: cool, frog: yes}, d: {things: hot, frog: false}}, expression: filter(.things cool), expected: []string{ D0, P[], (!!seq)::[{things: cool, frog: yes}]\n, }, },filter 与 select 的区别何时用哪个select的典型用法是先通过.[]把数组打散splat再逐元素过滤输出的是打散后的单个元素流而filter把“遍历 筛选 重新聚合”封装成一个操作符直接产出聚合后的序列。对比同一需求筛选出大于 1 的元素# 使用 select先打散再筛选 yq .[] | select(. 1) sample.yml # 使用 filter一步到位保持序列形态 yq filter(. 1) sample.yml两者的筛选逻辑一致但select适合后续还要对每个元素做逐项处理如继续| .name、| map(...)的场景filter适合只需要“拿到筛选后的集合”这一结果的场景表达更紧凑且天然维持输出为数组便于直接作为整体继续传给下游操作。从语法注册看二者都是 yq 的一等操作符filter在 lexer_participle.go 中注册为简单操作符simpleOp(filter, filterOpType)其类型定义见 operation.govar filterOpType operationType{Type: FILTER, NumArgs: 1, Precedence: 52, Handler: filterOperator, CheckForPostTraverse: true}其中NumArgs: 1表示它只接收一个表达式参数即括号内的筛选条件Precedence: 52决定了它与管道等操作符结合时的优先级。底层实现原理splat → select → collectfilter的实现位于 operator_filter.go其核心逻辑分为三步func filterOperator(d *dataTreeNavigator, context Context, expressionNode *ExpressionNode) (Context, error) { var results list.New() for el : context.MatchingNodes.Front(); el ! nil; el el.Next() { candidate : el.Value.(*CandidateNode) children : context.SingleChildContext(candidate) splatted, err : splat(children, traversePreferences{}) // 1. 打散把候选节点展开为逐元素上下文 filtered, err : selectOperator(d, splatted, expressionNode) // 2. 筛选对每个元素按表达式求布尔值 selfExpression : ExpressionNode{Operation: Operation{OperationType: selfReferenceOpType}} collected, err : collectTogether(d, filtered, selfExpression) // 3. 聚合把命中的元素重新收集为序列 collected.Style candidate.Style results.PushBack(collected) } return context.ChildContext(results), nil }打散splat调用 splat 把输入的候选节点数组或映射展开成逐元素上下文筛选select调用 selectOperator对每个元素求值expressionNode并借助isTruthyNode判断结果是否为真值——只要任一求值结果为真即保留该元素聚合collect通过 collectTogether 把命中的元素收集进一个新的!!seq序列节点并继承原候选节点的Style样式如块状/流式缩进风格。这三步正是“filter等价于map(select(exp))”的源码级印证map负责“遍历 聚合”的外壳见 operator_map.go 中同样的 splat → 求值 → collectTogether 结构select负责“布尔筛选”的内核。区别在于map会把每个元素的求值结果原样替换进去而filter只做保留/丢弃的二元判断。边界行为空结果与空数组filter对边界情况有明确的语义这些行为同样被测试用例锁定operator_filter_test.go无元素命中filter(. 4)作用于[1,2,3]输出空序列[]而不是报错或输出 null空数组输入filter(. 1)作用于[]输出空序列[]打散后继续管道filter(. 3)[]会把聚合结果再次打散输出1、2两个独立元素该场景标记为skipDoc不在文档中展示但验证了操作符的可组合性。这意味着你可以放心地把filter用于“可能没有匹配项”的数据下游无需额外判空。组合进阶把 filter 用在更复杂的表达式上filter的括号内是完整表达式因此可以与 yq 的其他操作符自由组合例如# 结合等于/不等于操作符 yq filter(.status active) sample.yml # 结合比较与布尔操作符筛选多个条件 yq filter(.age 18 and .age 65) sample.yml # 结合正则test 操作符做模式匹配 yq filter(.name | test(^prod-)) sample.yml # 对嵌套字段筛选后继续管道处理 yq filter(.things cool) | .[].frog sample.yml其中、!等比较操作符与and、or等布尔操作符的细节可分别参考仓库内 equals.md、compare.md 与 boolean-operators.md 的操作符文档正则匹配能力则在 string-operators.md 中有完整介绍。小结filter(exp)按布尔表达式筛选数组或映射的值输出保持为序列等价于map(select(exp))数组场景yq filter(. 3) sample.yml映射场景yq filter(.things cool) sample.yml筛选作用在值上底层实现为“打散 → select 筛选 → 重新聚合”三步流水线operator_filter.go筛选语义复用select的真值判断operator_select.go无匹配与空输入均安全返回空序列行为由测试用例锁定需要“直接拿到筛选后的集合”时优先用filter需要“打散逐项处理”时用select。【免费下载链接】yqyq is a portable command-line YAML, JSON, XML, CSV, TOML, HCL and properties processor项目地址: https://gitcode.com/GitHub_Trending/yq/yq创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价