Unicode 空白文字(Zs)の処理:Python の unicodedata を利用した正規化
Unicode にはさまざまな空白文字があり、文字列に混ざっていると厄介な問題が起きるリスクがあります。
import unicodedata
space_separators = [
('\u0020', 'SPACE'), # 通常のスペース
('\u00A0', 'NO-BREAK SPACE'), # ノーブレークスペース
('\u1680', 'OGHAM SPACE MARK'), # オガム文字スペース
('\u2000', 'EN QUAD'), # en quad
('\u2001', 'EM QUAD'), # em quad
('\u2002', 'EN SPACE'), # en space
('\u2003', 'EM SPACE'), # em space
('\u2004', 'THREE-PER-EM SPACE'), # 1/3 em space
('\u2005', 'FOUR-PER-EM SPACE'), # 1/4 em space
('\u2006', 'SIX-PER-EM SPACE'), # 1/6 em space
('\u2007', 'FIGURE SPACE'), # 数字幅スペース
('\u2008', 'PUNCTUATION SPACE'), # 句読点幅スペース
('\u2009', 'THIN SPACE'), # thin space
('\u200A', 'HAIR SPACE'), # hair space
('\u202F', 'NARROW NO-BREAK SPACE'), # 狭いノーブレークスペース
('\u205F', 'MEDIUM MATHEMATICAL SPACE'), # 数学用中スペース
('\u3000', 'IDEOGRAPHIC SPACE'), # 全角スペース(日本語)
]
for char, name in space_separators:
print(f'{unicodedata.category(char)} {unicodedata.name(char)}')
# Zs SPACE
# Zs NO-BREAK SPACE
# Zs OGHAM SPACE MARK
# Zs EN QUAD
# Zs EM QUAD
# Zs EN SPACE
# Zs EM SPACE
# Zs THREE-PER-EM SPACE
# Zs FOUR-PER-EM SPACE
# Zs SIX-PER-EM SPACE
# Zs FIGURE SPACE
# Zs PUNCTUATION SPACE
# Zs THIN SPACE
# Zs HAIR SPACE
# Zs NARROW NO-BREAK SPACE
# Zs MEDIUM MATHEMATICAL SPACE
# Zs IDEOGRAPHIC SPACE
Zs カテゴリーにある空白文字をいつもの半角スペースまたは日本語の全角スペースに統一したい、という場合、どうすればいいでしょうか。
import unicodedata
def is_unicode_whitespace(char):
return unicodedata.category(char).startswith('Z')
a = is_unicode_whitespace('あ')
b = is_unicode_whitespace(' ')
print(a) # False
print(b) # True
category は unicode character を引数とするため、is_unicode_whitespace は二文字以上の判定には使えません。
import unicodedata
def is_unicode_whitespace(char):
return unicodedata.category(char).startswith('Z')
a = is_unicode_whitespace('あい')
# TypeError: category() argument must be a unicode character, not str
文字列にあるさまざまな空白文字を一括で同じものにするには、次のようにします。
import unicodedata
def is_unicode_whitespace(char):
return unicodedata.category(char).startswith('Z')
def replace_all_unicode_whitespace(text, replacement=' '):
if not text:
return text
result = []
for char in text:
if is_unicode_whitespace(char):
result.append(replacement)
else:
result.append(char)
return ''.join(result)
s = 'あい うえお'
t = replace_all_unicode_whitespace(s, ' ')
print(s) # あい うえお
print(t) # あい うえお