文字與日常工具·文字工具包
不可見字元:不間斷空格、零寬度連接符號和修剪
· 背景
文字清理 統一碼 出版
調查看起來沒什麼的字元-不間斷空格、零寬度空格和連接符號、位元組順序標記-它們來自哪裡,哪些算是空白,以及如何尋找和刪除它們。
兩行不重複的相同行 — 隱形字元如何擊敗重複資料刪除和搜尋
兩行在編輯器中看起來可能相同,但無法透過相等性、搜尋或重複資料刪除檢查。一個可能包含普通的 U+0020 空格,而另一個包含 U+00A0(不間斷空格)。零寬度字元可以在不佔用任何可見寬度的情況下產生相同的問題,從而為發布者留下兩個明顯匹配的標籤,這些標籤仍然是不同的字串。
這不僅僅是裝飾性的。隱藏的程式碼點可以分割分析維度、破壞精確查找操作、保留重複行或使複製的識別碼無法通過驗證。在親眼重寫內容之前,保留原始程式碼的副本並系統地比較可疑字串。可見渲染是有關外觀的證據,而不是其底層 Unicode 序列匹配的證據。
它們來自哪裡 — 網頁、文字處理程序、表情符號序列和 PDF 中的複製貼上
隱形角色通常是透過普通工作來實現的。網頁使用不間斷空格將術語保持在一起,文字處理器保留面向佈局的間距,並 PDF 提取從定位字形重建文字。即使目標僅顯示熟悉的單字和間隙,這些系統之間的複製也可以將格式化字元帶入 CMS 欄位。
其他隱形標記是書寫系統或表情符號的有意部分。零寬度連接符號可以將表情符號元件組合成一個顯示的符號,而連接符號和非連接符會影響多個腳本中的形狀。來源很重要:「看不到它」並不意味著「可以安全刪除」。清理應該針對已診斷的工件,而不是每個前進寬度恰好為零的字元。
空白家族 — 普通、不間斷、狹窄和表意的空格,以及 JavaScript 的修剪所認為的空白
Unicode 包含的內容不僅僅是日常空間。 U+00A0 是不間斷空格,U+202F 是窄不間斷空格,U+3000 是表意空格。 JavaScript 空白處理包含這些字符,因此 `trim()`、`trimStart()` 和 `trimEnd()` 可以在它們出現在字串的相關邊緣時將其刪除。
文字工具包的行修剪在每行上呼叫這些 JavaScript 方法。它不會標準化內部間距,因此兩個單字之間仍保留不間斷的空格。其「不含空格的字元」統計資料會刪除與 JavaScript `s` 相符的字符,比 ASCII 空格更寬。使用該數字作為定義的測量,而不是排除每個不可見代碼點的承諾。
零寬度系列 — 零寬度空格、連接符號和非連接符、字連接符和位元組順序標記,它們根本不是空白
零寬度系列遵循不同的規則。 U+200B 零寬度空格、U+200C 零寬度非連接符、U+200D 零寬度連接符和 U+2060 單字連接符號是格式字元而不是 JavaScript 空白。因此普通 `trim()` 不會刪除它們。包含這些標記之一的行不會僅僅因為螢幕沒有顯示墨水而成為空白。
U+FEFF 有兩個相關的歷史:在編碼資料的開頭,它可以表示位元組順序標記,而在文字中,它充當零寬度不間斷空格。 ECMAScript 在其修剪空白集中包含 U+FEFF,這與 U+200B 到 U+200D 不同。因此,將整個零寬度系列視為一種空白將與實際的 JavaScript 行為相矛盾。
偵測它們 - 使用字元計數器來發現與您所看到的不匹配的計數,記住一些加入者會附加到鄰居並保持隱藏狀態
令人驚訝的計數可以提醒您隱藏的內容,但它無法識別每種情況。 ToolAcre 使用 `Intl.Segmenter` 計算字素簇(如果可用)。參與表情符號序列的連接器可能會幫助多個代碼點形成一個字素,因此添加或刪除它可以更改渲染,而不會產生代碼點計數器將顯示的簡單的單字元增加。
同時使用多個線索:失敗的精確匹配、意外的「無空格」結果、在支援 Unicode 的編輯器中檢查複製的文字,或對特定代碼點進行正則表達式搜尋。當 Segmenter 不可用時,回退計數器會使用程式碼點,因此結果也可能因瀏覽器功能而異。計數縮小了調查範圍;它不是隱藏字元掃描器或 Unicode 名稱檢視器。
偵測隱藏字元:計數提供線索,而不是完整的清單
對於已確認的複製貼上工件,請處理副本並在正規表示式模式下開啟「尋找和取代」。搜尋 `[]` 並替換為任何內容會刪除整個文字中的零寬度空格和嵌入的 U+FEFF 字元。該工具使用 JavaScript 的全域標誌編譯模式,報告替換計數,並在模式無效時保持文字不變。
不會自動將該模式擴大到 `[-]`。該範圍還刪除了 U+200C 和 U+200D,它們可以更改腳本形狀並將連接的表情符號拆分為單獨的符號。僅當檢查證明這些代碼點是不需要的時才添加這些代碼點。替換後,執行重複資料刪除並將輸出與發布前保留的原始內容進行比較。
工作範例:在去重複之前僅刪除已確認不需要的零寬度字符
此清理不會解決雙向控製字元、同形文字或與混淆文字相關的每個安全問題。方向標記可以改變視覺順序,而同形文字攻擊則使用彼此相似的不同可見字元。這兩個問題都不能透過刪除空格來解決,而且不加區分的不可見字元正規表示式可能會損壞合法的多語言內容,同時忽略實際風險。
此工具包也不會公開正規表示式標誌(例如 Unicode 或多行模式)、反白每個即將到來的符合項目或單獨逐步執行替換。替換整個文字中的所有操作,因此報告的計數和撤銷操作是重要的保障措施。對於原始程式碼、合法副本或不熟悉的腳本,請在進行批次編輯之前使用專用的 Unicode 工具檢查每個字元。
重點-隱形並不意味著無害;文字工具包的計數器和正規表示式查找和替換無需離開瀏覽器即可公開並刪除它們
隱形並不表示空洞、可互換或有害。不間斷空格是具有佈局語義的空白;零寬度連接符可以攜帶整形語義; U+FEFF 在 JavaScript 修剪下的行為再次不同。準確的清理首先是命名程式碼點,了解它可能存在的原因並確定目標是否仍然需要其功能。
使用文字工具包作為受控的瀏覽器端工作台:計數可以暴露差異,正規表示式查找和替換可以刪除精確定義的集合,而重複資料刪除可以確認隱藏的差異已消失。保留原始檔案,避免預設刪除連接器,並驗證渲染結果。狹隘的、可審查的修正比將所有看不見的 Unicode 視為碎片更安全。