nom 模糊过滤器源码详解:fuzzy 匹配与正则提取器的实现原理

发布时间:2026/8/23 13:43:03

nom 模糊过滤器源码详解:fuzzy 匹配与正则提取器的实现原理
nom 模糊过滤器源码详解fuzzy 匹配与正则提取器的实现原理【免费下载链接】nomRSS reader for the terminal项目地址: https://gitcode.com/gh_mirrors/nom1/nomnom 是一款运行在终端里的 RSS 阅读器按/就能在成千上万篇文章中快速筛选。它背后是一套精巧的过滤引擎正则提取器负责解析feed:、tag:等限定符fuzzy 模糊匹配负责标题搜索。本文带你完整读懂 nom 模糊过滤器源码搞透 fuzzy 匹配与正则提取器的实现原理。 一、nom 是什么30 秒认识这位终端 RSS 阅读器nom 用 Go 语言编写基于 Bubbletea 构建终端 UI用 Markdown 渲染文章内容支持本地 SQLite 离线阅读与 Miniflux / FreshRSS 后端同步。对读者来说最有价值的功能之一就是过滤在文章列表界面按/进入过滤模式输入关键词、feed:限定符或tag:限定符列表会实时刷新命中的字符还会被高亮。今天就来拆开这个功能的源码。 二、过滤引擎架构一条搜索词的三条命运整个过滤逻辑集中在internal/commands/filter.go核心流程只有 4 步NewFilterer接收原始搜索词先跑两轮正则提取先抽走feedname|feed|f前缀再抽走tag|t前缀剩下的残句成为纯标题搜索词FilterTerm.TitleFilter根据抽到的内容走三条分支之一CustomFilter把结果翻译成 Bubbletea 列表组件能懂的list.Rank。三条分支是整个引擎的灵魂源码里只有 6 行if len(f.FeedNames) 0 { ranks f.FilterAgainstStrings(f.FeedNames, targetFeedNames) } else if len(f.Tags) 0 { ranks f.FilterAgainstStrings(f.Tags, targetTags) } else { ranks fuzzy.Find(f.Term.Title, targetTitles) }见internal/commands/filter.goL141-L147。含义很直白有 feed 限定符→ 只按订阅源名称模糊匹配标题关键词被忽略有 tag 限定符→ 只按标签匹配都没有→ 对文章标题做 fuzzy 模糊搜索这是最常用的路径。这也是 README 里强调的过滤器不能混用行为的根源——feed:foo tag:news会忽略tag:部分因为 feed 分支优先。在匹配之前每篇文章先被编码成一个字符串由internal/commands/tui.goL42-L44的FilterValue()生成格式为文章标题||源名称||标签1||标签2过滤器端的GetIteminternal/commands/filter.goL63-L71按||切分还原出标题、源名和标签三个字段结构极简但足够高效。 三、正则提取器feed: 与 tag: 限定符如何被拆解ExtractFiltersForinternal/commands/filter.goL74-L121是最见功力的部分。它要回答一个问题搜索词里哪些部分是限定符哪个部分是关键词难点在于值里可能带空格所以 nom 支持三种写法双引号feed:tech blog、单引号feed:tech blog、反斜杠转义feed:the\ rust\ blog。为此它编译了两条正则complete : regexp.MustCompile( fmt.Sprintf((%s):(([^])|([^])|(([^\\ ]|\\ ))), strings.Join(tags, |)))complete完整匹配%s位置被替换成feedname|feed|f这样的别名表冒号后依次尝试双引号 → 单引号 → 无引号含\转义空格三种捕获组。源码注释特意提醒捕获组的顺序是有讲究的因为取值时按组3 → 组4 → 组5的优先级判断。incomplete未闭合匹配用户正在输入 feed:web 时引号还没敲完。此时 complete 匹配失败nom 会把这段半成品直接从搜索词里剥掉避免引号字符干扰标题模糊匹配。提取是一个for !done循环反复从搜索词中抠出完整的限定符同一限定符可以写多个如feed:foo feed:bar直到抠不动为止。最后有个精巧的细节——如果抠完限定符后标题变成空字符串nom 会把它替换成单个空格 防止空搜索词匹配全部文章。⚡ 四、fuzzy 模糊匹配为什么 intro 能搜出 Introduction走标题搜索分支时真正干活的是go.mod里声明的github.com/sahilm/fuzzy库。它做的是子序列模糊匹配搜索词的字符按顺序依次出现在目标里即可命中同时按连续、靠前、命中多等因素打出一个分数。单元测试internal/commands/filter_test.go里的用例完美诠释了这一点输入intro命中Introduction to Golang——不要求完整单词输入Go命中 3 篇文章Go 出现在标题中的三处输入golang精确命中 1 篇。每个命中结果是一个fuzzy.Match包含Index在列表中的位置、Score相关度和MatchedIndexes哪些下标字符命中用于 UI 高亮。 五、多限定符合并与稳定排序列表为什么不乱跳当你写了feed:tech feed:blog多个限定符时同一个源可能同时被两个限定符命中。FilterAgainstStringsL31-L60的解法很漂亮用map[int]fuzzy.Match以源的下标为键归组同一源被多次命中时只保留分数最高的那条最后用SortStableFunc按原始下标升序稳定排序。第 2 步的注释写得很直白this keeps the same order of items in the UI and prevents the items from being shuffled。也就是说过滤结果的相关度排序由sort.Stable(ranks)L149按分数完成但同分的结果保持列表原有顺序输入过程中列表不会剧烈跳动这是 TUI 体验上很贴心的一个决定。 六、接入 BubbleteaCustomFilter 只负责翻译过滤引擎与 UI 的胶水层只有 16 行CustomFilterL168-L184返回一个 Bubbletealist.FilterFunc每次输入变化时被调用——内部NewFilterer解析、Filter计算再把fuzzy.Match转成list.Rank保留MatchedIndexes让命中字符高亮显示。接线点在internal/commands/tui.goL262一行完成l.Filter CustomFilter(*cfg)。注意cfg被传入因为配置项filtering.defaultIncludeFeedName定义于internal/config/config.goL47会改变行为开启后普通关键词也会顺带匹配源名称等价于自动帮你加了f:前缀——代价是无法再同时过滤多个源。 七、单元测试用 5 组用例守住过滤行为internal/commands/filter_test.go用 6 条模拟文章覆盖了全部关键路径测试函数守住的边界TestFilter_SimpleTextSearch精确词、模糊词、多命中、零命中TestFilter_FeedNameSearchfeed:/feedname:/f:三种前缀等价性TestFilter_TagSearchtag:/t:前缀与多标签命中TestFilter_QuoteHandling双引号、单引号、反斜杠空格TestFilter_DefaultIncludeFeedName配置开关改变默认搜索范围想验证某个搜索词的行为加一条用例跑go test ./internal/commands/即可无需启动 TUI——这正是过滤逻辑与 UI 解耦带来的好处。 八、实战速查3 种过滤写法结合源码理解这里给一个日常速查表你想找什么输入什么标题含关键词的文章golang某订阅源下的所有文章f:tech或feed:tech blog带空格要加引号/转义打了某标签的订阅源t:ai或tag:programming 相关模块路径过滤引擎internal/commands/filter.go、测试internal/commands/filter_test.go、TUI 接线internal/commands/tui.go、配置定义internal/config/config.go、依赖声明go.modfuzzy 库在 L14。总结nom 的模糊过滤器麻雀虽小五脏俱全正则提取器用完整/未完成双正则优雅地处理了引号与空格等边界情况fuzzy 匹配让搜索宽容而精准稳定排序保证了 TUI 不跳帧最后用一个薄胶水函数接入 Bubbletea。约 180 行代码 300 行测试是一个小而美的终端过滤引擎范例。想继续深挖建议按NewFilterer → ExtractFiltersFor → Filter → CustomFilter这条调用链顺次阅读源码。【免费下载链接】nomRSS reader for the terminal项目地址: https://gitcode.com/gh_mirrors/nom1/nom创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

Pink的Configuration类如何工作:机器人模型加载与前向运动学完全实践指南

Pink的Configuration类如何工作:机器人模型加载与前向运动学完全实践指南

2026/8/23 13:43:03

Pink的Configuration类如何工作:机器人模型加载与前向运动学完全实践指南 【免费下载链接】pink Python inverse kinematics using Pinocchio and QP solvers 项目地址: https://gitcode.com/gh_mirrors/pink1/pink Pink 的 Configuration 类是把机器人模型加…

java-saml完整指南:3步为Java应用添加企业级SAML单点登录(SSO)支持

java-saml完整指南:3步为Java应用添加企业级SAML单点登录(SSO)支持

2026/8/23 13:33:02

java-saml完整指南:3步为Java应用添加企业级SAML单点登录(SSO)支持 【免费下载链接】java-saml Java SAML toolkit 项目地址: https://gitcode.com/gh_mirrors/jav/java-saml java-saml 是广泛使用的开源 Java SAML 工具包&#xff08…

Oops Framework登录流程全解:Cocos Creator 3.x事件驱动的服务器连接与角色数据加载实战

Oops Framework登录流程全解:Cocos Creator 3.x事件驱动的服务器连接与角色数据加载实战

2026/8/23 13:33:02

Oops Framework登录流程全解:Cocos Creator 3.x事件驱动的服务器连接与角色数据加载实战 【免费下载链接】oops-framework 基于 Cocos Creator 3.x 版本开发的游戏框架,此项目为 Oops Framework 教程项目,如果使用框架制作游戏项目可下载 oop…

为什么OCR总是认错字?uvdoc-npu昇腾NPU文档图像矫正模型完全入门指南

为什么OCR总是认错字?uvdoc-npu昇腾NPU文档图像矫正模型完全入门指南

2026/8/23 14:33:05

为什么OCR总是认错字?uvdoc-npu昇腾NPU文档图像矫正模型完全入门指南 【免费下载链接】uvdoc-npu 用户可直接获取在华为昇腾 NPU 上运行的文档图像矫正模型,用于消除拍摄畸变和透视变形以提升OCR准确率。该项目将PaddleOCR的UVDoc模型逐算子迁移至PyTorc…

ipatool IPA下载完整指南:从Apple ID登录到批量获取只需5分钟

ipatool IPA下载完整指南:从Apple ID登录到批量获取只需5分钟

2026/8/23 14:33:05

ipatool IPA下载完整指南:从Apple ID登录到批量获取只需5分钟 【免费下载链接】ipatool Command-line tool that allows searching and downloading app packages (known as ipa files) from the iOS App Store 项目地址: https://gitcode.com/GitHub_Trending/ip…

MaxKB 开源企业知识库问答系统:1 条 Docker 命令跑起来,直接提问你的文档

MaxKB 开源企业知识库问答系统:1 条 Docker 命令跑起来,直接提问你的文档

2026/8/23 14:33:05

MaxKB 开源企业知识库问答系统:1 条 Docker 命令跑起来,直接提问你的文档 【免费下载链接】MaxKB 🔥 MaxKB is an open-source platform for building enterprise-grade agents. 强大易用的开源企业级智能体平台。 项目地址: https://gitco…

OpenKore实战手册:从0到全自动只需一次配置

OpenKore实战手册:从0到全自动只需一次配置

2026/8/23 14:33:05

OpenKore实战手册:从0到全自动只需一次配置 【免费下载链接】openkore A free/open source client and automation tool for Ragnarok Online 项目地址: https://gitcode.com/gh_mirrors/op/openkore 打怪的时候你最清楚那种感觉:点攻击、点拾取、…

Gridfinity Extended快速开始教程:10分钟搭建OpenSCAD环境并生成第一个3D打印收纳盒

Gridfinity Extended快速开始教程:10分钟搭建OpenSCAD环境并生成第一个3D打印收纳盒

2026/8/23 14:33:05

Gridfinity Extended快速开始教程:10分钟搭建OpenSCAD环境并生成第一个3D打印收纳盒 【免费下载链接】gridfinity_extended_openscad Gridfinity Extended OpenSCAD Model 项目地址: https://gitcode.com/gh_mirrors/gr/gridfinity_extended_openscad Gridfi…

使用geemap进行Google Earth Engine Python API入门指南

使用geemap进行Google Earth Engine Python API入门指南

2026/8/23 14:23:04

使用geemap进行Google Earth Engine Python API入门指南 【免费下载链接】geemap A Python package for interactive geospatial analysis and visualization with Google Earth Engine. 项目地址: https://gitcode.com/gh_mirrors/ge/geemap 概述 本文介绍如何使用gee…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/23 0:02:09

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/23 0:02:09

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/23 0:02:09

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

[光学原理与应用-521]:对光的错误理解与纠偏

[光学原理与应用-521]:对光的错误理解与纠偏

2026/8/23 0:02:09

首先光是一种能量的载体和形态,宏观上观察到的光是由无数个微观的光量子组成的,每个光子在产生的瞬间,其在真空的空间中以确定不变的速度沿着一个初始的方向一直向前,在微观层面,每个光量子的运动轨迹是以波函数所展现…

SIP通话转接原理与REFER方法实战解析

SIP通话转接原理与REFER方法实战解析

2026/8/23 0:02:09

1. 通话转接不是“挂断再拨号”,而是SIP会话的动态重定向你有没有遇到过这样的场景:客服坐席A正在和客户通电话,突然需要把这通对话无缝转给专家坐席B,客户完全感知不到中间的断连——既没听到忙音,也没被要求重新拨号…

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

Kolla-ansible单节点OpenStack部署实战:从环境准备到排坑指南

2026/8/23 0:02:09

1. 为什么选择Kolla-ansible来部署单节点OpenStack?如果你正在寻找一种能把OpenStack从“概念”快速变成“可用的实验环境”的方法,那么Kolla-ansible几乎是当前最主流、最省心的选择。我见过太多人卡在手动编译依赖、配置服务、处理版本冲突的泥潭里&am…

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

2026/8/22 2:02:26

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…

导师推荐!2026最新AI论文工具测评与实用推荐

导师推荐!2026最新AI论文工具测评与实用推荐

2026/8/22 4:13:47

2026年真正好用的AI论文工具,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

告别游戏崩溃:XCOM 2模组管理器的智能革命

告别游戏崩溃:XCOM 2模组管理器的智能革命

2026/8/22 1:32:34

告别游戏崩溃:XCOM 2模组管理器的智能革命 【免费下载链接】xcom2-launcher The Alternative Mod Launcher (AML) is a replacement for the default game launchers from XCOM 2 and XCOM Chimera Squad. 项目地址: https://gitcode.com/gh_mirrors/xc/xcom2-lau…