從文字中去除口音(變音符號)是指將帶有變音符號的拉丁字母,例如 é、ç、ñ、ø、ł 和 ž,替換為對應的純 ASCII 等效字元 —— café 變成 cafe、señor 變成 senor、Zürich 變成 Zurich、Łódź 變成 Lodz —— 使清理後的字串可用於僅支援 ASCII 的系統、slug 產生器、資料去重,以及識別碼比對。「how to remove accents from keyboard」(如何從鍵盤移除口音)這個說法誤導多於幫助,因為這項工作幾乎從來不是關於鍵盤配置。帶有口音的字元已經存在於剪貼簿中的 CSV 欄位、通訊錄、產品型錄,或需要與不支援 Unicode 的舊系統比對的姓名欄位裡。這項工作是文字清理,而不是新的輸入快捷鍵,清理發生在你取得原始文字之後,而不是在你輸入的時候。這就是 Remove Accents from Text 所設計處理的日常情境:貼上任何文字,點擊一次,複製一個真正可在下游使用的清理後字串。
標準的快速腳本是兩行程式碼 —— 將文字正規化為 Unicode NFD 並刪除組合標記 —— 表面上它是有效的。JavaScript 的 String.prototype.normalize() 方法 也內建了相同的方法,並被 Unicode 正規化形式規範所推薦。但是這個方法會在一個眾所周知的字母家族上悄然失效,這些字母完全不帶有可分離的口音;同時它也會默默地損壞另一個腳本家族,這些腳本分解的方式與帶口音的拉丁字母完全相同。對於任何正在清理通訊錄、為 URL 製作 slug,或在編碼方式不一致的系統之間比對姓名的人來說,這兩個問題都是真實存在的。

為何僅靠 Unicode 正規化會留下字母
帶口音的拉丁字母,例如 é、à、ç 和 ñ,在 Unicode 中是儲存為一個基礎字母加上一個組合標記。組合標記是一個獨立的碼位 —— 銳音符 U+0301、抑音符 U+0300、軟音符 U+0327 —— 因此最直觀的作法是用 NFD 正規化將配對拆開,然後刪除第二個碼位。這種配對方式正是標準方法的基礎,並且完全按照規範所述的方式運作。
問題在於,這個方法僅適用於在 Unicode 字元資料庫中有分解條目的字母。有一整個家族的拉丁字母沒有分解條目,因為它們的變音符號是與字母本身融合在一起,而不是疊加在字母上方:
- 帶斜線和橫線的字母: ø、Ø、đ、Đ、ħ、Ħ、ŧ、Ŧ、ł、Ł
- 其他不可分解的字母: 無點 i(ı)、eth ð、Ð,以及 kra ĸ
- 連字和雙字母: æ、Æ、œ、Œ、ß
由於 Unicode 字元資料庫對這些字母都沒有記錄分解條目,因此 NFD 正規化會原封不動地將它們傳遞過去。在 Łódź 上執行一般的兩行腳本,你會得到原樣的 Łódź。Remove Accents from Text 內建了一張明確的折疊對照表,涵蓋這些字母,且每個條目都對照 Unicode 字元資料庫進行驗證,因此 ø 會變成 o、ł 會變成 l、đ 會變成 d,產生的結果在 ASCII 環境中確實可用。
如何使用 Remove Accents from Text
這個工具的設計目的是用三個步驟完成一件事,並且不需要任何設定、帳號或上傳 —— 整個頁面都在你的瀏覽器中執行,所以資料不會離開你的電腦。
- 貼上文字 將包含帶口音或特殊拉丁字元的文字貼到輸入框中。姓名、地址、CSV 欄位、slug 候選字串,以及產品標題都可以同樣良好地運作。
- 選擇你的選項: 決定是否要將連字以及像 ß 和 þ 這樣的字母拼寫出來(æ→ae、œ→oe、ß→ss、þ→th),以及是否要保留或移除非拉丁腳本。音譯切換預設為開啟,因為資料清理通常需要這些轉換,但你可以將其關閉,以便在剝離真正的變音符號時保留原始字母。
- 點擊 Remove accents, 然後查看輸出區正下方顯示的變更次數,並複製清理後的結果。變更次數是精確的,因此你可以確認工具在處理大量貼文時確實進行了處理,並在輸入已經是乾淨的情況下確認變更次數為零。
你可以將結果再次送回工具中執行,你將會看到變更次數為零。這是經過刻意設計的 —— 這個操作是等冪的(idempotent) —— 即使同一段文字被處理兩次,這也使得該工具可以安全地放入重複執行的流程中而不會產生飄移。預組成型和分解型的輸入,例如單一碼位的 é 和兩個碼位的 e + ́,也會產生相同的結果,因為該工具在剝離標記後會重新組合成 NFC,因此你的來源如何儲存該字元並不影響結果。
工具不會處理的部分(以及為何這很重要)
與工具執行什麼同等重要的是它拒絕執行什麼。希臘文和斯拉夫文(西里爾文)字母在 Unicode 中分解的方式與帶口音的拉丁字母完全相同:ά 分解為 α 加上 U+0301、ё 分解為 е 加上 U+0308。一個單純的標記剝離器會悄悄地將 ζ 重寫為 α、ё 重寫為 е,損壞它從未被要求清理的腳本中的文字。Remove Accents from Text 只會移除附加在拉丁基礎字母上的標記,因此希臘文、斯拉夫文(西里爾文)、中文、日文、韓文、天城文以及 emoji 都會逐位元組地原封不動通過。天城文的母音符號在文法上是字母而非口音,因此從不會被視為可移除的標記。
一個可選的嚴格模式可以在你確實需要僅含 ASCII 的輸出時,直接刪除非拉丁字元。它預設為關閉,因為更常見的需求是在清理拉丁腳本文字的同時,保留外語段落不變。
| 輸入類型 | 範例 | 純 NFD + 剝離 | Remove Accents from Text |
|---|---|---|---|
| 帶口音的拉丁字母 | café、señor、Zürich | cafe、senor、Zurich | cafe、senor、Zurich |
| 不可分解的拉丁字母 | Łódź、ø、đ、þ | Łódź、ø、đ、þ(未變更) | Lodz、o、d、th(þ 在音譯切換開啟時) |
| 連字和雙字母 | æ、œ、ß | æ、œ、ß(未變更) | ae、oe、ss(切換開啟時) |
| 希臘文與斯拉夫文 | ά、ё | α、е(已損壞) | ά、ё(已保留) |
| 非拉丁腳本與 emoji | 中、😀 | 中、😀(已保留) | 中、😀(已保留) |
希臘文和斯拉夫文的這一列是最讓人措手不及的。一個會悄悄將 ά 重寫為 α 的工具不只是沒幫助,它是有破壞性的 —— 拉丁字母 α 看起來相似但是是不同的碼位,當腳本被改變時,意義可能會完全不同。在常見情況下,跳過這些腳本是更安全的預設行為,而嚴格模式是選擇性加入的,並非預設行為。
音譯 vs 口音移除
將 ß 轉換為 ss 與將 é 轉換為 e 並非同類型的操作。前者是將一個字母拼寫為兩個字母;後者是移除加在基礎字母上的標記。Remove Accents from Text 原則上將這兩者分開,音譯切換有明確命名、有說明文件並且獨立區隔,讓使用者能清楚看到他們何時獲得的是音譯、何時獲得的是真正的口音剝離。該切換預設為開啟,因為資料清理幾乎總是希望將 ß→ss、æ→ae、œ→oe、þ→th 及其大寫形式進行轉換,但你可以將其關閉,以便在剝離真正的變音符號的同時保留這些字母。頁面以淺白的語言標示出差異,而不是模糊兩者之間的界線,這在需要稽核紀錄以確切說明哪些內容被變更時是很重要的。
這類清理在哪些情況下真正能幫上忙
經典的使用情境是實務的,而非理論上的。你有一份從以完整 Unicode 儲存姓名的系統匯出的通訊錄,你需要將它與僅以 ASCII 儲存的舊系統進行去重。你正在建立 URL slug,而 Warszawa 或 São Paulo 一直中斷你的 slug 正則表示式。你有一份產品型錄,其中 Zürich、Québec 和 Łódź 都需要能以純 ASCII 進行搜尋,因為搜尋引擎尚未針對變音符號進行調整。你正在將使用者輸入正規化,以便送入正則表示式、資料庫索引,或不支援 Unicode 的 API。在所有這些情境中,修復方法都相同:產生一個下游系統真正能處理的純淨拉丁字母版本。
該工具也適合用於重複性的作業。由於輸出是等冪的,且輸入上限為一百萬個字元,你可以將其納入一個每晚處理產生的 CSV 的腳本中,永遠不需要為同一個字母撰寫特例。沒有需要追蹤的上傳、不需要佈建的帳號,也沒有資料曾經離開你的瀏覽器分頁的風險。
開始之前值得了解的限制
Remove Accents from Text 是一個拉丁腳本的變音符號移除工具,附帶有完整說明文件的音譯規則,而非一個通用的音譯工具。它不會將俄文羅馬化、不會產生漢語拼音,也不會將希臘文轉換為拉丁字母。像 ð 和 ĸ 這類特殊字母是依照慣例而非任何 Unicode 規則進行折疊的,網頁公開披露了這一點,而不是將其隱藏。輸入上限為一百萬個字元,並以單一線性處理程序執行,因此即使是大量的貼文也能立即返回,但如果你打算將整個資料庫匯出透過它進行處理,了解這個限制是值得的。最後,該工具僅處理拉丁腳本的文字清理 —— 如果你的資料需要大小寫校正、slug 格式化,或標點符號移除,你應該將它與另一個專門的工具搭配使用,而不是期望這個工具完成所有事情。
如果你正在權衡各種選項,How to Remove Duplicate Names in Word Documents 對此有詳細介紹。
如果你正在權衡各種選項,How to Remove Special Characters From a Text File Safely 對此有詳細介紹。