发布时间:2026/8/25 8:55:21
正则表达式的边界在哪里?Fountain遗留版FountainParser源码剖析 正则表达式的边界在哪里Fountain遗留版FountainParser源码剖析【免费下载链接】FountainAn open source implementation of the Fountain screenplay formatting language.项目地址: https://gitcode.com/gh_mirrors/foun/FountainFountain 是一个用纯文本编写剧本screenplay的开源格式而本文要剖析的 FountainParser 正是其 Objective-C 实现中的“遗留版”正则表达式解析器。它用最朴素的方式——16 条正则规则——把一份.fountain剧本文件解析成结构化的元素数组。读懂它你就能看清正则表达式在真实文本解析中的能力边界在哪里。Fountain 项目是什么FountainParser 又扮演什么角色Fountain 的设计哲学和 Markdown 类似原始文件本身必须对人类友好。一份剧本即使以纯文本打开也应该看起来像剧本。在这个开源项目中各组件分工清晰FNScriptFountain/FNScript.h门面类负责读写 Fountain 文件并持有内容FNElementFountain/FNElement.h数据模型剧本中每个段落场景标题、对白、动作等都映射为一个元素FastFountainParserFountain/FastFountainParser.m重写的逐行解析器默认使用速度快约 10 倍FountainParserFountain/FountainParser.m遗留版正则解析器本文主角FountainRegexesFountain/FountainRegexes.m全部正则规则与替换模板的集中定义FountainWriterFountain/FountainWriter.m反向输出把元素数组写回 Fountain 文本对外 API 只有四个方法定义在Fountain/FountainParser.h中分别解析标题页与正文来源可以是文件路径或字符串。正则解析的三遍扫描流程FountainParser 源码核心思路打开Fountain/FountainParser.mparseBodyOfString:方法把整个解析过程拆成了三遍第一遍处理块注释。正则还不够聪明无法直接匹配跨行注释所以先把注释内部的换行符替换成占位符见NEWLINE_REPLACEMENT常量同时把、转义为lt;、gt;把...保护成::trip::——这些脱敏操作是为了避免后续正则误伤。第二遍正则轰炸全文。这是整个设计最精彩的抽象。解析器维护着两个严格一一对应的数组——16 个 pattern 和 16 个 templateNSArray *patterns [UNIVERSAL_LINE_BREAKS_PATTERN, BLOCK_COMMENT_PATTERN, ...]; NSArray *templates [UNIVERSAL_LINE_BREAKS_TEMPLATE, BLOCK_COMMENT_TEMPLATE, ...]; // Validate the array counts (protection against programmer stupidity) if (arrayMax ! [templates count]) { return nil; }每条 pattern 负责识别一种剧本元素对应 template 负责把它替换成中间标记格式例如pattern识别目标template 输出SCENE_HEADER_PATTERNINT. / EXT. 开头的场景标题Scene Heading.../Scene HeadingCHARACTER_CUE_PATTERN大写的人物名Character.../CharacterDIALOGUE_PATTERN人物名后的对白Dialogue.../DialogueTRANSITION_PATTERNCUT TO: / FADE OUT. 等转场Transition.../TransitionSYNOPSIS_PATTERN以开头的概要行Synopsis.../Synopsis经过这轮替换整份剧本变成了一段类似 XML 的伪标记文本。这个中间格式是三遍扫描的关键——它把复杂的识别问题第二遍和简单的提取问题第三遍彻底解耦。第三遍拆标签、装模型。用一条通用正则([a-zA-Z\\s])([^]*)\\/[a-zA-Z\\s]提取所有标签内容对逐个还原转义字符包装成FNElement对象。剩余的细节处理场景编号#12#、居中文字、双人对话^等也在这一步用少量辅助正则完成。正则的边界在哪里从 FountainRegexes 看三类典型难题规则集中在Fountain/FountainRegexes.m约 110 行好读逐条对照能清楚看到正则方案的能力边界1. 行首/行尾边界依赖前后断言。场景标题的正则用(?\n)后行断言确保匹配从换行开始(?\n)(([iI][nN][tT]|[eE][xX][tT]|[^\\w][eE][sT]...)注意大小写兼容是靠[iI][nN][tT]这种逐字符穷举实现的——没有(?i)局部标志可读性立刻下降。2. 排除法识别负向字符类是双刃剑。人物名正则CHARACTER_CUE_PATTERN的核心是[^a-z\\s\\/\\n]——以小写字母和空白开头的不是人物名。这种先排除再放行的写法非常依赖上下文假设一旦剧本里出现全小写的角色名就会失配。3. 有状态、跨行的语境正则搞不定只能打补丁。例如双人对话两个角色共用一段对白靠^标记需要回看之前若干个元素才能判断FountainParser.m第三遍里专门写了一段倒序循环来补齐前一个角色元素的isDualDialogue标志。跨行注释也是先压平再处理。这些补丁正是正则方案的典型局限规则是无状态的而剧本语法是有语境的。README 中也坦诚承认这些正则与完整测试用例并不完全兼容the regular expressions are not fully compliant with the tests。为什么遗留版被 FastFountainParser 取代项目最终用逐行扫描的FastFountainParserFountain/FastFountainParser.m取代了正则方案原因在 README 里说得很直白降低正则依赖——规则改起来更不容易顾此失彼性能提升约 10 倍——16 条正则全文轰炸意味着整份文档被反复扫描多次开销很大Fountain/FNScript.h中的FNParserType枚举保留了两个选项注释甚至带有劝退语气// These methods are here so you can use the old parser. // You should move away from the old parser ASAP.默认走快速解析器只有显式传入FNParserTypeRegex才会调用遗留版。测试用例如FountainTests/Big Fish.fountain等对两条解析路径做交叉验证保证行为一致。给初学者的 4 个可迁移经验 读完这份遗留源码可以沉淀出正则用于文本解析的通用判断准则优先识别无状态的行级标记#12#场景编号、分页符这类是正则的舒适区用中间标记格式解耦识别与提取比写一条巨型正则可维护得多模式数组与模板数组数量一致性校验FountainParser.m第 91 行的防御代码能防住改了 pattern 忘了改 template这类低级失误当需要跨元素语境判断时果断放弃纯正则改为逐行状态机——这正是 FastFountainParser 的设计动机快速上手如何获取并运行 Fountain 解析器如果想在本地体验这套代码只需三步克隆仓库git clone https://gitcode.com/gh_mirrors/foun/Fountain用 Xcode 打开Fountain.xcodeproj注意链接标志需加入-licucoreRegexKitLite 依赖跑一遍FountainTests下的单元测试配合FountainTests/Simple.fountain等样例文件观察解析结果Sample Project Mac/与Sample Project iOS/两个示例工程演示了FNScript的实际用法项目基于 MIT 协议发布见根目录LICENSE你可以自由地把这套文本 → 结构化元素的解析思路移植到自己的项目里。【免费下载链接】FountainAn open source implementation of the Fountain screenplay formatting language.项目地址: https://gitcode.com/gh_mirrors/foun/Fountain创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

2026/8/25 11:26:02

LLM智能体恒定上下文技能学习:从状态表示到工程实践

1. 从历史到状态:为什么LLM智能体需要“恒定上下文”技能学习?如果你最近在关注大语言模型智能体领域,可能会发现一个有趣的现象:大家似乎都在忙着给智能体“打补丁”。无论是通过监督微调让智能体学会使用特定工具,还…

2026/8/25 11:26:02

Windows服务器等保2级加固实操指南:从账户策略到防火墙配置

1. 从“能用”到“合规”:为什么Windows服务器必须做等保2级加固?最近帮一个朋友的公司处理他们线上业务服务器的安全审计,发现一个挺普遍的现象:很多技术团队把Windows Server装好、应用部署上去、网络调通,就觉得“服…

2026/8/25 11:26:02

ORCA框架解析:多智能体协作如何解决复杂文档视觉问答

1. 项目缘起:当文档理解遇上复杂推理最近在做一个智能文档处理的项目,遇到了一个挺有意思的挑战:用户上传了一份包含图表、表格和大量文字的年度财报PDF,然后问了一个问题:“公司去年在研发上的投入占营收的比例是多少…

2026/8/25 11:26:02

工信部开展网络安全专项整治,严打非法爬虫、数据倒卖行为

随着数字经济高速发展,各行各业数据采集、交互、传输频次大幅激增,数据已然成为企业核心生产资产。但随之而来的是黑灰产产业化、规模化的数据窃取与倒卖乱象,非法爬虫泛滥、个人信息肆意泄露、违规跨境传数、接口裸奔漏数等安全问题频发&…

2026/8/25 11:21:00

三消游戏核心算法:并查集实现高效消除判定与工程实践

1. 从“三消”到“巧判”:一个被低估的核心算法做游戏开发的朋友,尤其是接触过休闲益智类项目的,对“消消乐”(三消)这个品类肯定不陌生。市面上从《Candy Crush Saga》到《开心消消乐》,无数成功产品验证了…

2026/8/25 1:04:19

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

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

2026/8/24 1:12:32

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

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

2026/8/24 8:17:29

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

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

2026/8/25 0:04:14

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南

三步把QQ空间历史说说导出到本地:GetQzonehistory 极简指南 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory Meta Description:GetQzonehistory 是一个QQ空间历史说…

2026/8/25 0:04:14

洛谷 P7912:[CSP-J 2021 T4] 小熊的果篮 ← 双向链表

【题目来源】 https://www.luogu.com.cn/problem/P7912 【题目描述】 小熊的水果店里摆放着一排 n 个水果。每个水果只可能是苹果或桔子,从左到右依次用正整数 1,2,…,n 编号。连续排在一起的同一种水果称为一个“块”。小熊要把这一排水果挑到若干个果篮里&#x…

2026/8/24 13:42:17

实测才敢推 AI论文网站 2026最新测评与推荐

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

2026/8/24 18:13:48

2026必备!AI论文网站测评:最新推荐与深度对比

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

2026/8/25 1:08:14

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

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