【Python】文字列が英数字かどうかを判定する(正規表現)

Tips

目的

Pythonで言語処理AIを使ってテキスト学習させたいのだが、そのためにその単語が英数字かどうかを判断する必要があった。

そのためにいろいろな方法を検証してみたので備忘録として記載する。

 

isalnumを利用する

Googleにて調べると、str型に以下の関数が用意されているらしい。

  • isdecimal : 数字かどうか
  • isalpha  : 英字かどうか
  • isalnum  : 英数字かどうか  ※戻り値は全てbool型

これを利用して文字列の英数字判定ができるのではないかと考えた。

というわけでテスト用のプログラムをさくっと書いてみる。

# coding:utf-8

# チェック対象の文字列
checkWord = ['あいうえお', 'あiうeお', 'あいう123', 'abcd', 'ABCD', 'AbCd', '01234', 'ABCD1234', 'AbCd1234']

# 英数字チェック関数
def checkStr(word):
  print(word)
  print('isdecimal: ', word.isdecimal()) # 数字かどうか
  print('isalpha: ', word.isalpha()) # 英字かどうか
  print('isalnum: ', word.isalnum()) # 英数字かどうか

def main():
  for s in checkWord:
    print('----------')
    checkStr(s)

if __name__ == "__main__":
  main()

 

実行結果はこちら。

----------
 あいうえお
 isdecimal:  False
 isalpha:  True
 isalnum:  True
----------
 あiうeお
 isdecimal:  False
 isalpha:  True
 isalnum:  True
----------
 あいう123
 isdecimal:  False
 isalpha:  False
 isalnum:  True
---------- 
 abcd
 isdecimal:  False
 isalpha:  True
 isalnum:  True
----------
 ABCD
 isdecimal:  False
 isalpha:  True
 isalnum:  True
----------
 AbCd
 isdecimal:  False
 isalpha:  True
 isalnum:  True
----------
 01234
 isdecimal:  True
 isalpha:  False
 isalnum:  True
----------
 ABCD1234
 isdecimal:  False
 isalpha:  False
 isalnum:  True
----------
 AbCd1234
 isdecimal:  False
 isalpha:  False
 isalnum:  True

なぜか日本語(平仮名)が英字判定されてしまっていることが分かる。

原因はこちらのサイトから引用

Unicode文字データベースでLetterとして定義されているもの、つまり、Unicodeの一般カテゴリプロパティがLm, Lt, Lu, Ll, LoのいずれかをもつものがTrueとなる。
アルファベットや平仮名、カタカナ、漢字などがTrueとなる。

https://note.nkmk.me/python-str-num-determine/

つまり、この関数では完全な英数字判別が不可能であることが分かった。

 

正規表現を利用する

正規表現を利用すれば、英数字やもっと複雑な判定(記号を含む判定など)を行うことができる。

pythonで正規表現を使用するには、reモジュールを使用すればよい。※詳細はこちら

テストプログラムをざっくりと作成。

# coding:utf-8

import re


# 正規表現用
lower = [re.compile(r'^[a-z]+$'), 'lower']       #英字(小)
upper = [re.compile(r'^[A-Z]+$'), 'upper']       #英字(大)
alpha = [re.compile(r'^[a-zA-Z]+$'), 'alpha']    #英字(大小)
digit = [re.compile(r'^[0-9]+$'), 'digit']       #数字
alnum = [re.compile(r'^[a-zA-Z0-9]+$'), 'alnum'] #英数字

# チェック対象の文字列
checkWord = ['あいうえお', 'あiうeお', 'あいう123', 'abcd', 'ABCD', 'AbCd', '01234', 'ABCD1234', 'AbCd1234']

Reg = [lower, upper, alpha, digit, alnum]


# 判定
def checkReg(word):
  print(word)
  for r in Reg:
    result = r[0].match(word) is not None
    print(r[1] + ': ', result)


def main():
  for s in checkWord:
    print('----------')
    checkReg(s)
  
# 直接実行されたときはmain関数を呼び出す
if __name__ == "__main__":
  main()

 

実行結果

----------
 あいうえお
 lower:  False
 upper:  False
 alpha:  False
 digit:  False
 alnum:  False
----------
 あiうeお
 lower:  False
 upper:  False
 alpha:  False
 digit:  False
 alnum:  False
----------
 あいう123
 lower:  False
 upper:  False
 alpha:  False
 digit:  False
 alnum:  False
----------
 abcd
 lower:  True
 upper:  False
 alpha:  True
 digit:  False
 alnum:  True
----------
 ABCD
 lower:  False
 upper:  True
 alpha:  True
 digit:  False
 alnum:  True
----------
 AbCd
 lower:  False
 upper:  False
 alpha:  True
 digit:  False
 alnum:  True
----------
 01234
 lower:  False
 upper:  False
 alpha:  False
 digit:  True
 alnum:  True
----------
 ABCD1234
 lower:  False
 upper:  False
 alpha:  False
 digit:  False
 alnum:  True
----------
 AbCd1234
 lower:  False
 upper:  False
 alpha:  False
 digit:  False
 alnum:  True

ちゃんと判定できてるっぽい。

 

ちなみに、match関数は条件に合致したらSRE_Match objectを返し、合致しなければNoneを返す。

result = r[0].match(word) is not None

今回はこの行で無理やりbool型に変換している。

※NoneでなければTrue、それ以外であればFalse

もし変換せずにそのまま出力させたら出力結果は以下の感じとなる。

 abcd
 lower:  <_sre.SRE_Match object; span=(0, 4), match='abcd'>
 upper:  None
 alpha:  <_sre.SRE_Match object; span=(0, 4), match='abcd'>
 digit:  None
 alnum:  <_sre.SRE_Match object; span=(0, 4), match='abcd'>

条件分岐させたいのであれば、Noneかどうかで分岐させればよい。

 

結論

文字列が英数字かどうかを判断するには以下の関数を使用すればよい。

import re

def checkAlnum(word):
  alnum = re.compile(r'^[a-zA-Z0-9]+$')
  result = alnum.match(word) is not None
  return result

引数が英数字であればTrue、違うのであればFalseを返す関数。

戻り値がTrue,Falseなので、ifの条件にそのまま利用することができる。

 

コメント

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