Pythonで文字列のバイト数を簡単に計算する方法(lenb関数)

Python

Pythonで文字列をバイト単位でカウントするlenb関数を作成するには?

Pythonでは、Visual Basic for Applications(VBA)において提供されているLenB関数と同等の機能を持つ、文字列のバイト数を計算するための関数を標準のライブラリ内に備えていません。この機能は特に帳票印刷の際に文字列の幅を正確に制御し、印刷結果を見た目上美しく整える必要がある場面で求められます。

Pythonでは直接的にこのような機能を提供していないため、文字列のバイト数を精確にカウントし印刷物の見た目を整えたいというニーズに応えるのが難しいという状況があります。しかし、Pythonの標準ライブラリの一つであるunicodedataモジュールを活用することにより、VBAのLenB関数と同様の動作を実現する関数を自作することが可能です。

この記事では、Pythonで自作のlenb関数を作成するための具体的な手順について紹介します。

lenb関数のサンプルコード

まずは、lenb関数のサンプルコードを紹介します。

import unicodedata

def lenb(countstring):
    """
    文字列の長さをバイト数でカウントする関数

    Args:
        countstring (str): カウントする文字列

    Returns:
        int: 文字列のバイト数。全角文字は2として半角文字は1としてカウント

    Example:
        >>> lenb('abc')  # 全て半角文字
        3
        >>> lenb('こんにちは')  # 全て全角文字
        10
        >>> lenb('abcこんにちは')  # 半角と全角の混在
        13
    """

    length = 0

    # 1文字ずつ処理
    for char in countstring:
        # unicodedata.east_asian_widthを用いて文字が全角('F', 'W', 'A')か半角(それ以外)を判断
        if unicodedata.east_asian_width(char) in 'FWA':
            length += 2  # 全角文字の場合、2バイトとして加算
        else:
            length += 1  # 半角文字の場合、1バイトとして加算

    return length




##############################################################
# 関数のテスト
if __name__ == "__main__":

    print("\n数字")
    text = "0123456789"
    print("len  ", len(text))
    print("lenb ", lenb(text))

    print("\n全角数字")
    text = "0123456789"
    print("len  ", len(text))
    print("lenb ", lenb(text))

    print("\nかな")
    text = "アイウエオカキクケコ"
    print("len  ", len(text))
    print("lenb ", lenb(text))

    print("\n全角かな")
    text = "あいうえおカキクケコ"
    print("len  ", len(text))
    print("lenb ", lenb(text))

    print("\n半角記号")
    text = "[]:;/.,#$~"
    print("len  ", len(text))
    print("lenb ", lenb(text))

    print("\n全角記号")
    text = "「」:;¥・。#$~"
    print("len  ", len(text))
    print("lenb ", lenb(text))

    print("\nローマ数字")
    text = "ⅠⅡⅢⅣⅤⅥⅦⅧⅨⅩ"
    print("len  ", len(text))
    print("lenb ", lenb(text))

    print("\nエスケープシーケンス")
    text = "\a\b\f\n\r\t\v\\\'\""
    print("len  ", len(text))
    print("lenb ", lenb(text))

実行結果

実行結果は以下の通りです。

数字
len   10
lenb  10

全角数字
len   10
lenb  20

かな
len   10
lenb  10

全角かな
len   10
lenb  20

半角記号
len   10
lenb  10

全角記号
len   10
lenb  20

ローマ数字
len   10
lenb  20

エスケープシーケンス
len   10
lenb  10

文字の幅の判定方法

lenb関数は半角文字を1バイト全角文字を2バイトとして文字列の長さをバイト数としてカウントします。具体的にはif unicodedata.east_asian_width(char) in 'FWA':の処理でunicodedataモジュールを使用して文字列の各文字の幅を判定しバイト数を加算しています。

文字の幅の判定は次のような考え方となります。

2バイト判定

‘F’(Fullwidth; 全角)
  • 全角英数などが該当します。
  • 例: 「A」、「a」、「1」、「¥」
‘W’(Wide; 広)
  • 漢字、かな文字、句読点などが該当します。
  • 例: 「漢」、「あ」、「、」
‘A’(Ambiguous; 曖昧)
  • アンビグアス文字は、言語やフォントによって全角表示される可能性がある文字。ギリシア文字やキリル文字などが該当します。
  • 例: 「◎」、「Ω」、「Я」

1バイト判定

‘Na’(Narrow; 狭)
  • ナロー(半角)文字は、英数字や一部の記号など、幅が狭い文字です。
  • 例: 「A」、「1」、「?」
‘H’(Halfwidth; 半角)
  • 半角幅を持つ文字です。半角カナなどがこれに該当します。
  • 例: 半角カタカナ「カ」、「サ」
‘N’(Neutral; 中立)
  • 全角でも半角でもない。アラビア文字などが該当します。

本サンプルプログラムでは2バイト判定してそれ以外は1バイト判定で処理しているのでFWAで処理を行っています。

最後に

Pythonでは標準でlenb関数のような関数は提供されていませんが、lenb関数を作成することで同様の機能を実現することができます。

同じ考え方を利用して、バイト幅で文字を切り出す関数LeftB、RightB、MidB関数の記事もありますので興味のある方は参照してみてはいかがでしょうか。

コメント

タイトルとURLをコピーしました