MENTAの相談でよくエクセルやメール送信の自動化の相談を受けるのですが、その中でメール本文などを自動化する際に文字列の長さを判定することがたまにあり、その際に全角と半角の区別をつけて文字列の長さを計算しないと文章がズレることがあります。
文字列の文字数をカウントする
まず文字列は、len関数で長さをカウントできます。
>>> len('abcde')
5
>>> len('こんにちは')
5
>>> len('銀河鉄道777')
7
ここで注目したいのはabcdeとこんにちはの文字列の長さが同じ5である点です。
Python上では同じ長さですが実際にテキストに起こすと以下のようにズレます。
abcde
こんにちは
なのでこの数字をそのまま鵜呑みにしてメール本文などのテキストを自動生成すると作ったテキストがなんか思っていたのと違う、みたいな現象がおきます。
unicodedataでユニコード文字の幅の種類を調べる
こういう時に便利なのが「unicodedata」という標準ライブラリでこのライブラリの.east_asian_width()というメソッドでを調べることができます
戻り値は文字列で意味は以下のようになります。
種類 | 内容 |
---|---|
F | 全角。全角英数など。 |
H | 半角。半角カナなど。 |
W | 全角。漢字やかななど。 |
Na | 半角。半角英数など。 |
A | 曖昧。ギリシア文字など。 |
N | 中立。アラビア文字など。 |
実際に判定してみたのが以下になります。
>>> import unicodedata
#全角英数
>>> unicodedata.east_asian_width('A')
'F'
>>> unicodedata.east_asian_width('1')
'F'
>>> unicodedata.east_asian_width(' ')
'F'
#半角カナ
>>> unicodedata.east_asian_width('イ')
'H'
#全角の漢字や「かな」
>>> unicodedata.east_asian_width('漢')
'W'
>>> unicodedata.east_asian_width('・')
'W'
>>> unicodedata.east_asian_width('、')
'W'
>>> unicodedata.east_asian_width('。')
'W'
全角と半角を考慮して文字列の長さを判定する
これを利用して全角と半角を加味した文字列の長さを計算します。
具体的にはunicodedata.east_asian_width(c)
の結果によって全角文字の場合は2、半角文字の場合は1で計算して、文字列の長さを計算しています
# 半角と全角を加味して文字数を計算する関数を新たに作成 def count_str_length(text): import unicodedata text_counter = 0 for c in text: j = unicodedata.east_asian_width(c) if 'F' == j: text_counter = text_counter + 2 elif 'H' == j: text_counter = text_counter + 1 elif 'W' == j: text_counter = text_counter + 2 elif 'Na' == j: text_counter = text_counter + 1 elif 'A' == j: text_counter = text_counter + 2 else: text_counter = text_counter + 1 return text_counter
<使用例>
print(count_str_length('abcde')) #5 print(count_str_length('こんにちは')) #10 print(count_str_length('銀河鉄道777')) #11
こういった感じでunicodedataを使用することで、全角と半角を考慮した文字列の長さが計算できるようになります。
コメント