正则匹配文本文件中的 3 种换行符 (行尾)
讨论
错误示范:
- 错误示范 1:
\n—— 不匹配 Windows 行尾(CRLF); - 错误示范 2:
\r\n|\n—— 不匹配旧式 mac 行尾(CR); - 错误示范 3:
[\r\n]{1,2}—— 错误匹配“LFCR”; - 错误示范 4:
\r?\n—— 不匹配旧式 mac 行尾(CR); - 错误示范 5:
\n|\r|\r\n—— CR 和 LF 被拆开,如果存在 CRLF 将匹配出两个子串; - 错误示范 6:
\r\n?|\n—— 这个的 bug 很难发现,问题在于:如果文件中存在 LFCRLF,则 LF 和 CRLF 都被匹配,但这种情况下应该只有 CRLF 才对; - 错误示范 7:
\r\n|\n|\r—— 问题同上。
正确示范:\r?\n|(?<!\n)\r —— 使用零宽断言。
这个正则 永远不会匹配到 LFCR;但也有弱点,即 LFCRLF 会匹配两个子串:LF 和 CRLF;但对于长度不大于 2 的纯 LF、CR 序列,都能够正确匹配。
所以就有了更正确一些的示范:\r\n|(?<!\r\n)\n(?!\r\n)|(?<!\r\n|\n)\r(?!\r\n|\n) —— 看起来很长但思路很简单:
- 优先匹配 CRLF;
- 否则,匹配前后都没有 CRLF 的 LF;
- 否则,匹配前后都没有 CRLF 或 LF 的 CR。
- 否则,拒绝。
(你也可以调整单独 CR 和单独 LF 的优先级,但 CRLF 的优先级总是最高的)
当存在长度小于等于 3 的纯 LF、CR 构成的序列时,这个正则都能给出正确的匹配,但 LFCRCR 除外,它会匹配两个子串,即 LF 和末尾的 CR;为了解决这个问题就必须进一步增加规则。
我们发现,这样下去是没完没了的……正则表达式的长度取决于你要实现正确匹配的纯 LF、CR 序列的最大长度。
结论
对于不那么极端的情况,\r?\n|(?<!\n)\r 就可以正确匹配了。
抬杠
任何有限长的正则表达式 RRR 都无法正确匹配任意无限长的序列 SSS 中可接受的子串 σR(S)\sigma_R(S)σR(S) ∈ Σ\SigmaΣ(Σ\SigmaΣ 是所有可接受的子串集合,且 card(Σ)>1card(\Sigma) > 1card(Σ)>1),使匹配到的子串集合 card(Σ′)=1card(\Sigma ') = 1card(Σ′)=1.
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐


所有评论(0)