一位 WP Adminify 客戶曾經向我發送了他的插件設定的兩個匯出 - "更新前,一切都正常;之後,管理選單被破壞。沒有其他改變。&引用;兩個 JSON 斑點,每個大約有 340 行。我並排讀了兩遍,並自信地同意他的觀點:相同。什麼都沒有改變。一定是我們的錯誤。
這是't。當我最終不再相信自己的眼睛並分散兩個檔案時,它位於第 217 行:選單角色鍵已遺失 "administrator" 到 "administrator "- 有尾隨空間。一個看不見的字元。我親自讀過它兩次,因為人眼比較字串;它們模式匹配形狀,並且 administrator 和 administrator 具有相同的形狀。
那張支持票永久改變了我的規則: 如果兩篇文章的長度超過大約十行,我會選擇#39;t 透過閱讀來比較它們。曾經。 差異演算法沒有模式匹配的捷徑來欺騙 - 它比較每個字元並準確報告不同的內容。這 文字差異工具 在 toolz。dev 上,您會在瀏覽器中執行此操作,這意味著客戶配置、合約和未發布的程式碼永遠不會離開您的電腦。這裡'差異的實際工作原理以及如何很好地使用它。
TL;DR: 切勿在視覺上比較超過幾行的文字 - 眼睛會錯過尾隨空格、交換數字和單字編輯。將兩個版本貼到 文字差異工具:綠色 = 新增,紅色 = 刪除,由相同的邁爾斯演算法系列計算
git diff. 使用 線路模式 對於程式碼和配置, 文字模式 對於散文和合約。對於結構化數據, JSON 差異 透過意義而不是文字進行比較。一切都運行客戶端。
差異演算法實際上如何運作?
核心思想:找到 最長的公共子序列 兩個文本的 (LCS) - 以相同順序出現在兩個文本中的最長行序列(或單字或字元)。 LCS 中的所有內容都是 "不變。"無論'版本 A 中留下的 s 是刪除;無論'版本 B 中留下的 s 是加法。 A&引用;修改並引用;行只是一個刪除和一個恰好相鄰的加法。
有效計算此值的標準方法來自 Eugene Myers' 1986年論文, &引用; O(ND)差分演算法及其變體和引用;。 優雅的部分就是複雜性界限所說的: N 是輸入大小,但是 D 是 差異的數量. 兩個幾乎相同的文本無論多長時間幾乎都會立即出現差異,因為演算法'工作規模取決於它們的差異,而不僅僅是大小。 That'這就是為什麼差異兩行相差一行的 300 行配置感覺瞬間 - 該演算法幾乎什麼都不做,這正是您的眼睛做最多工作但失敗的情況。
同一演算法系列是其中的預設引擎 git diff,GNU diff以及您'曾經使用過的大多數比較工具。 (Git 也提供) patience 和 histogram 有時會產生更多人類可讀的相同變化分組的變體 - 設定 變化是相同的,表示方式也不同。)
一個重要的非顯而易見性:差異並不總是唯一的。如果您在兩個現有空白行之間新增一條空白行,"哪個&引用;空白行是新的確實是含糊不清的,不同的工具可能會突出顯示不同的工具。兩個答案都是正確的。
行、字或字元差異 - 何時採用哪種模式?
您比較的粒度會改變輸出的優點。犯錯是人們發現差異輸出和報價的主要原因;吵雜。&報價;
| 線級 | 詞級 | 人物等級 | |
|---|---|---|---|
| 比較 | 全線作為原子 | 個別詞 | 個別人物 |
| 單字編輯顯示為 | 刪除整行+重新新增 | 只是這個詞 | 只是換了字母 |
| 最好 | 程式碼、配置、CSV 行 | 散文、合約、文件 | 打字錯誤、雜湊值、編碼字串 |
| 弱點 | 長段落編輯:你仍然在隊伍中狩獵 | 回流/重新包裝的文字會發出噪音 | 大編輯無法讀取 |
| 經典用戶 | git diff |
法律黑線/編輯評論 | &引用;這兩個 API 金鑰看起來相同&引用; |
具體例子。原創: The quick brown fox jumps over the lazy dog. 修改: The quick red fox leaps over the lazy cat.
- 線路模式 將整個句子標記為已更改 - 準確、無益。
- 文字模式 準確地突出顯示
brown→red,jumps→leaps,dog→cat. - 角色模式 這裡太過分了,但是它'是唯一會流行的模式
admlnistratorvsadministrator.
經驗法則:結構化文字(每行一個有意義的語句)想要行模式;流動文字想要文字模式;字元模式是一個放大鏡,當另外兩個說「"」時,您就會拉出它;改變&引用;你可以'看看為什麼。我的尾隨空間錯誤是規範字元模式情況。
什麼時候獨立差異工具比 Git 更好?
Git's diff 非常好 對於生活在同一儲存庫中的事物. 令人驚訝的比較工作量不't:
支持門票。 我的介紹中的場景 - 兩個設定從客戶匯出。他們'不在任何回購中。兩者都貼到 文字差異工具 答案以秒為單位出現,而不是兩次讀數失敗。
配置漂移。 暫存 nginx 配置與生產 nginx 配置。當前的 .env 與事情破裂前的替補相比。 git diff can't 查看兩個不同伺服器上的檔案;複製貼上可以。
格式化程式驗證。 您在文件中運行 Prettier(或 PHPCS,或 Black)並希望對其更改充滿信心 僅格式化. 區分前後:如果你看到空格、引號和分號以外的任何東西,格式化程式就會觸及邏輯,你現在就想知道。
兩個 API 回應。 分期返回一個 JSON 主體,生產返回另一個 JSON 主體,前端僅在分期中中斷。不同的反應。 (特別是對於 JSON,更喜歡 JSON 差異- 它比較了解析的結構,因此鍵序和空格 don't 會產生誤報。運行兩個有效負載 json 格式化程式 首先,如果您想要可讀的文字差異。)
文件和合約。 供應商退貨並報價;相同的合同,但有一些小的更新。&報價;字模差異是您如何在一份 40 頁的文件中發現付款條件從 Net 30 到 Net 15 的方式。編輯和律師永遠知道這一點--他們稱之為黑線或紅線。
翻譯和本地化文件。 比較a的兩個版本 .po 在將其發送回翻譯器之前查看哪些字串實際更改的文件 - 真正的 WP Adminify 工作流程,可節省重新翻譯 400 個未更改字串的費用。
共同點:當兩個版本都以文字形式存在時,您可以選擇一個不同的工具來回答和引用;發生了什麼變化? &引用;機械地。由於 toolz。dev 工具是客戶端,因此貼上客戶's 配置或未簽署的合約不't 將其傳輸到任何地方 - 與其餘的參數相同 隱私優先的工具箱.
如何在不欺騙自己的情況下讀取差異輸出?
顏色約定是通用的: 紅色是舊版本'獨家內容(已刪除),綠色是新版本's(已新增),未更改的文字會使上下文變得簡單。更改的行顯示為紅線,後面跟著綠色替換。
使差異審查真正可靠的三個習慣:
將版本放在正確的插槽中。 左側(或第一個欄位)為舊/原始,右側為新/修改。交換它們,每個新增內容都讀作刪除 - I'因此,我們已經觀看人們調試錯誤的方向十分鐘。如果輸出向後看,可能是這樣。
在開始之前決定噪音是什麼。 比較重新格式化的程式碼?空白變化是雜訊 - 標準化或忽略它們。比較 YAML 配置?空白是 意義- 縮排是 YAML 中的結構,因此驗證兩邊 yaml 驗證器 並將每個空間視為訊號。相同的工具、相反的政策以及錯誤的選擇要么掩蓋了噪音的真正變化,要么隱藏了它。
閱讀每一塊,而不僅僅是第一塊。 客戶'尾隨空間是變化#1(共1 個)。但是,當差異顯示四個變化並且第一個變化解釋了您的症狀時,停止閱讀的誘惑很強烈- 並且變化#3 有時是下週咬你的。差異已經做了困難的部分;唐'在最後一步重新引入人工採樣誤差。
文字差異可以告訴你什麼?#39;t?
值得誠實地了解限制:
- 移動的區塊讀作刪除+新增。 從檔案頂部剪切一個函數並將其貼在底部:差異報告它刪除並添加,而不是移動。一些專門的工具檢測移動;普通 LCS 沒有't。
- 它比較的是文本,而不是意義。
0.1 + 0.2和0.3不同(它們)但也不同 表現得好 浮點不同 - 反之亦然"key": 1vs"key": 1.0您的語言可能在文字上不同,但在語義上相同。結構化比較(如 JSON 差異) 縮小了資料格式的部分差距。 - 二進制內容超出了範圍。 圖像、PDF(位元組)、可執行檔 - 文字差異需要文字。首先提取文本,或使用特定於格式的工具。
- 案例和編碼是按字面意思比較的。
README傾斜readme,UTF-8 捲曲引號 提取 ASCII 直引號,即使它們在大多數字體中看起來相同。 (另一個眼睛形狀模式陷阱,演算法的另一個勝利。)使用 預標準化 變形器 如果情況應該'對於您的比較很重要。
常見問題
我可以比較文件,還是只比較貼上的文字?
的 文字差異工具 適用於貼上的文字:開啟任何編輯器中的每個文件,複製,貼上兩面。這使得它與格式無關 - 任何 ' 的可讀文字(程式碼、設定、CSV、SQL、散文)都可以進行比較,無論擴充如何。
比較有尺寸限制嗎?
實際限制是您的裝置's 內存,因為處理是在瀏覽器內進行的。數千行的檔案立即比較;邁爾斯演算法's 成本與數量成比例 差異,因此即使是大但相似的文字也能保持快速。數十萬行差異巨大的行可能需要幾秒鐘的時間。
我應該使用哪種差異模式來編寫程式碼?
行模式。程式碼自然是每行一個語句,因此行級輸出乾淨地映射到您對變更的看法。僅當一行被標記為已更改時,才切換到單字或字元模式,您可以't 發現其中的差異 - that's 通常為空格、引號或單一字元。
哪種模式最適合合約和散文?
文字模式。散文的修改通常是單字替換和在長段落中插入子句;行模式會標記整個段落並讓您繼續搜尋。字級突出顯示準確地顯示哪些單字發生了變化 - 與法律黑線的方法相同。
diff 會修改或儲存我的文字嗎?
不,反白僅存在於渲染輸出中;您的輸入文字沒有變化,並且由於該工具完全在客戶端運行,因此兩個版本都不會在任何地方傳輸或儲存。關閉選項卡,文字就消失了。
為什麼差異會突出顯示一條看起來相同的線?
幾乎總是看不見的字元:尾隨空格、製表符與空格、Windows \r\n vs Unix \n 行結尾、不間斷空格或 Unicode 相似項(捲曲與直引號)。這正是人眼看不到的變化類別,而差異演算法總是能抓住--我的尾隨空間支援票就是其中之一。
它可以檢測移動的文字嗎?
不是作為移動。基於標準 LCS 的差異報告移動區塊已從舊位置刪除並在新位置新增。如果您懷疑移動,請搜尋 "新增"原文中的文字 - 文件中其他地方的精確命中證實了這一點。
JSON Diff 與 Text Diff 有何不同?
文字差異比較字元; JSON 差異 解析文檔並比較結構。重新排序的鍵、更改的縮排和尾隨逗號產生零結構差異,因此您只能看到實際值和鍵的變化。只要雙方都有效,就使用它 JSON;當文字 diff 為 't 時,回退到文字 diff。
比較文字時如何忽略空白或大小寫?
首先決定空格是雜訊還是訊號:在重新格式化的程式碼中它是噪聲,但在 YAML 或 Python 縮排中它是結構。當它是雜訊時,在擴散之前對兩邊進行歸一化 - 折疊重複空格,剝離尾隨空格,並使行尾保持一致 - 因此只剩下真正的變化。在比較之前忽略大小寫,兩個文字小寫,因為 diff 預設將 README 和 Readme 視為不同。
git diff 使用什麼演算法?
預設情況下,git diff 使用 Myers 演算法的變體,與 Eugene Myers' 中的最長公共後續方法相同;大多數 diff 工具共享的 1986 年論文。 Git 還提供耐心和直方圖變體,可以更可讀地對更改進行分組,但它們報告相同的差異集 - 僅顯示更改。該工具使用相同的邁爾斯演算法系列。



