数据和电子表格 · CSV 清理器
CSV 解析器如何处理字段中的引号、嵌入逗号和换行符
· 工作原理
csv 解析 数据格式
按逗号分割有效,直到字段包含逗号、引号或换行符。这篇文章解释了真正的 CSV 解析器使用的小型状态机、为什么存在引用规则,以及当引用被破坏时修复工具会做什么。
带逗号的地址字段将每一列向右移动 - 为什么天真的拆分不能解析
一旦邮政地址、注释或产品描述包含该字符,在每个逗号处拆分行就会失败。当解析器位于带引号的字段之外时,分隔符仅结束一个字段。在引号内,相同的字节属于该值,并且必须不变地到达预览。
ToolAcre 通过测试证明了这一点,而不是假设 CSV 是简单文本。引用注释中包含逗号的分号文件仍会被检测为分号分隔,因为每个候选在其矩形形状评分之前都会被解析为行。原始标点计数永远不会决定方言。
引用规则 — 包含分隔符、引号或换行符的字段用双引号括起来,内部引号加倍
包含所选分隔符、双引号、换行符或回车符的字段在序列化期间被引用。带引号的字段内的文字双引号由两个相邻的引号表示。解析时,该对向单元格贡献一个引号,并且不会关闭该字段。
引号仅在出现在空字段的开头时才打开带引号的状态。在未加引号的值(例如 12" 管道中)中,引号仍保留文字数据。该实现选择经过测试,可防止文本中间的测量标记吞没后续列。
作为状态机的解析器 — 内部引号与外部引号,以及一次一个字符如何决定字段的结束位置
核心循环跟踪当前字段、当前行和 `inQuotes` 状态。在引号之外,分隔符推送字段,CR、LF 或 CRLF 推送行。在引号内,除了引号之外,每个字符都会被附加,引号要么形成转义对,要么退出引号状态。
这一单字符级数解释了为什么简单的正则表达式或行分割很脆弱。换行符是否结束记录取决于之前的输入,引号是否关闭字段取决于下一个引号。解析器通过字符串准确地携带最小状态。
嵌入换行符 — 为什么一行可以跨越多行以及为什么基于行的工具(例如 grep 或 wc)错误计数记录
带引号的字段可能包含 LF、CRLF 或单独的 CR,并且这些字符保留在值内。因此,一个逻辑记录可以在文本编辑器中占据多个显示行。使用面向行的命令计算物理行不一定计算数据行。
在结束引号之后,下一个分隔符或记录结尾恢复结构含义。 ToolAcre 的测试断言嵌入式 LF 和嵌入式 CRLF,然后验证仅生成一行。此行为不是从 RFC 标签推断出来的;它由交付的状态机直接执行。
损坏的引用 — 吞没文件其余部分的不平衡引用,以及修复工具如何一致地重新引用字段
大纲承诺修复报价,但未关闭的报价本质上是不明确的。 ToolAcre 根据引用状态开始的行报告 `UNCLOSED_QUOTE` ,并将随后的所有内容读入一个字段。它不会发明平仓或重新报价预期记录。
这种保守的失败保留了所使用的文本以供检查,并避免假装知道后面的引用或换行符是否意味着数据。更正源或重新生成导出,然后重新加载。序列化可以规范一个成功解析的表;它无法恢复由于格式错误的源而变得不可知的行边界。
报告了损坏的引用但未修复;未封闭的字段消耗剩余的文本
使用 `name,note` 作为标题,然后一行包含 Ada 和包含逗号和换行符的注释,另一行的注释为 `She said "hi"`。在源 CSV 中,引用长注释并将内部引号写为 `""hi""`。解析器返回两个数据行并保留两个特殊字符。
当使用最少的引用进行序列化时,普通名称不需要引号,而注释字段则被引用,因为它们包含结构字符。即使冗余源引号消失,再次解析该输出也会产生相同的标题和单元格。数据相等,而不是逐字节样式,定义了此往返。
这不包括什么 - 使用反斜杠转义的方言,以及当引用确实不明确时猜测意图的启发式方法
反斜杠转义方言位于解析器之外。引号前的反斜杠在这里没有特殊的状态机含义;它仍然是文本,而引用则根据双引号规则进行解释。一旦开盘报价仍然不匹配,该工具也会拒绝猜测意图。
在导入为另一个转义约定配置的数据库转储时,这些边界很重要。在加载之前识别生产者的方言,或使用 RFC 风格的引用导出。默默地识别几个不兼容的转义规则的解析器可以将文字反斜杠转换为控制语法并隐藏不匹配。
尊重引号和行保持完整 - ToolAcre CSV Cleaner 的引用修复如何生成标准解析器正确读取的文件
遵守引用状态会将分隔符和记录结尾保留在它们所属的单元格内。 ToolAcre 还处理三种行结束形式,删除前导 UTF-8 BOM 并报告行宽不匹配。这些行为是结构读取的独立部分,而不是搜索和替换技巧的集合。
有效解析后,序列化将嵌入的引号加倍并引用任何需要保护的字段,默认情况下使用 CRLF 输出。在出现无效的未关闭报价后,停止并从源证据中修复。该工具可以标准化已知的细胞;它并不声称要重建一个不可知的表。