資料與電子表格 · 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 輸出。在出現無效的未關閉報價後,停止並從來源證據中修復。該工具可以標準化已知的細胞;它並不聲稱要重建一個不可知的表。