HOWTO · Python

在 Python 中刪除字串中的特殊字元

本教程介紹瞭如何在 Python 中刪除字串中的所有特殊字元。

本頁內容

若要移除 Python 字串中的字元,請先決定要保留哪些字元。搭配 str.isalnum() 使用字串推導式或 filter(),可以保留 Unicode 字母和數字;正規表示式可以設定為保留空白字元,而 str.translate() 則可針對指定字元集合進行處理。以下範例使用 "Hey! What's up bro?",讓各種規則更容易理解。每個程式碼範例都會自行定義輸入並列印轉換後的字串,因此可以各自獨立執行。

如何判定哪些字元屬於特殊字元

「特殊字元」沒有唯一的判定規則。它可能只指標點符號,也可能包括標點符號和空白字元,或是所有非 ASCII 字母與數字的字元。請根據清理後字串的用途選擇規則:顯示名稱可能需要保留空格,精簡的識別碼則可能不需要。

Python 字串使用 Unicode。str.isalnum() 能辨識 Unicode 字母和數字,因此可以保留 é 和 中 等字元。相較之下,使用 [a-zA-Z0-9] 的模式只涵蓋 ASCII 字母和數字。因此,除非為這些方法指定相同的字元規則,否則它們會產生不同結果。

使用字串推導式移除非英數字元

如果結果只應包含字母和數字,請使用搭配 str.isalnum() 的字串推導式。str.join() 會將保留下來的字元組合成新字串。這項規則也會移除空格和標點符號。

original = "Hey! What's up bro?"
cleaned = "".join(char for char in original if char.isalnum())
print(cleaned)
HeyWhatsupbro

此判斷條件會保留 Unicode 字母和數字,也會保留 ASCII 字元。例如,é 這類字母會保留下來;空格、撇號和標點符號則會被省略。

使用 filter() 篩選字元

內建函式 filter() 會對每個字元套用判斷條件,並回傳一個迭代器,其中包含判斷結果為真的字元。傳入 str.isalnum 後,保留的 Unicode 字母和數字會與字串推導式相同,而 str.join() 則會將迭代器轉回字串。和字串推導式一樣,這種做法也會移除空白字元。

original = "Hey! What's up bro?"
kept = filter(str.isalnum, original)
cleaned = "".join(kept)
print(cleaned)
HeyWhatsupbro

如果想重複使用某個判斷條件,或已經定義好判斷條件,可以使用 filter()。對於這種簡單的字串轉換,字串推導式能以更精簡的方式表達相同規則。

使用 str.translate() 移除指定字元集合

如果知道要移除哪些字元,且希望其他字元都保留下來,可以使用 str.translate()。str.maketrans() 會建立一個轉換表,將選定的字元對應為移除。以下字元集合會移除常見的 ASCII 標點符號;空格和未列出的字元都會維持不變。

original = "Hey! What's up bro?"
characters_to_remove = "!@#$%^&*()_-+=<>,./?;:'\"[]{}\\|`~"
table = str.maketrans("", "", characters_to_remove)
cleaned = original.translate(table)
print(cleaned)
Hey Whats up bro

請依照輸入內容調整 characters_to_remove 中的字元。這個方法不會移除所有可能被視為標點符號的字元:未列出的字元,包括非 ASCII 標點符號,都會留在結果中。

使用正規表示式移除字元

使用 re.sub() 以指定模式取代所有符合條件的字元。此模式只保留 ASCII 字母和數字,因此空格和標點符號都會被移除。特色插圖展示了相同規則。字母和數字的範圍只適用於 ASCII;如果文字包含範圍外的字母,請改用能辨識 Unicode 的規則。

import re

original = "Hey! What's up bro?"
pattern = r"[^a-zA-Z0-9]"
cleaned = re.sub(pattern, "", original)
print(cleaned)
HeyWhatsupbro

提供的執行證據記錄了此範例產生上方所示的輸出。若要保留空白字元,可在允許的字元集合中加入 \s,例如 r"[^a-zA-Z0-9\s]"。Python 的正規表示式字元類別和旗標能表達其他規則,但請確認所選模式符合資料中的語言和字元。

使用 map() 和 Lambda 轉換字元

map() 會對每個字元套用函式,並回傳一個迭代器。Lambda 可以在字元是 Unicode 字母、數字或空白字元時回傳原字元,否則回傳空字串。將這些結果合併,就能建立清理後的字串;此規則會保留空白字元,包括定位字元和換行字元。

original = "Hey! What's up bro?"
cleaned = "".join(
    map(lambda char: char if char.isalnum() or char.isspace() else "", original)
)
print(cleaned)
Hey Whats up bro

如果轉換需要的邏輯超出單純的包含條件判斷,這種逐字元處理方式便是另一種選擇。如果規則只是保留字母和數字,請改用字串推導式或 filter() 範例。

選擇符合字元規則的方法

  • 若要使用直接易讀的規則來保留 Unicode 字母和數字並移除空白字元,請選擇搭配 str.isalnum() 的字串推導式。
  • 若要傳入可重複使用的判斷條件,請選擇 filter();範例採用相同的 str.isalnum() 規則。
  • 若要移除已知字元集合,同時保留其他所有字元(包括空白字元和未列出的標點符號),請選擇 str.translate()。
  • 若要用模式描述要移除或保留的字元,請選擇 re.sub()。範例中的 ASCII 範圍會移除空白字元;若要處理 Unicode 文字或保留空白字元,請調整模式。
  • 若要逐字元套用轉換邏輯,請選擇搭配 Lambda 的 map()。範例會保留 Unicode 字母、數字和空白字元。

處理姓名或自然語言文字前,請先決定如何處理重音符號、非拉丁文字系統和空格。處理識別碼或符合特定通訊協定的輸入時,請精確遵循文件所載的字元集合,不要依賴籠統的「特殊字元」概念。