Python
正規表現
python2.7

[修正] Python 文字列の英数字判定でハマった

More than 1 year has passed since last update.

追記

記事に不備がありましたので、本文の下の追記部分もお読みください。


ハマった点

ある日のこと

Google App Engine (Python) でWebアプリを書いていました。

Webサービスで、パスワードに使える文字を判定したい時ってありますよね?

調べたら 文字列.isalnum() で英数字かどうか確かめられるそうなので、それを使ったんです。

しかしおかしい。

password = 'abc123'

password.isalnum() #--> True

password = u'あいう'
password.isalnum() #--> True えっ?

どうやら全角文字は isalnum メソッドでは True と判断されるみたいです。

ひどい...


解決策

仕方ないので正規表現を使います。

ついでに色々用意しました。

import re

#半角小文字
lowerReg = re.compile(r'^[a-z]+$')
def islower(s):
return lowerReg.match(s) is not None

#半角大文字
upperReg = re.compile(r'^[A-Z]+$')
def isupper(s):
return upperReg.match(s) is not None

#半角英字
alphaReg = re.compile(r'^[a-zA-Z]+$')
def isalpha(s):
return alphaReg.match(s) is not None

#半角数字
digitReg = re.compile(r'^[0-9]+$')
def isdigit(s):
return digitReg.match(s) is not None

#半角英数字
alnumReg = re.compile(r'^[a-zA-Z0-9]+$')
def isalnum(s):
return alnumReg.match(s) is not None

#半角英数字orアンダースコア
alnum_Reg = re.compile(r'^[a-zA-Z0-9_]+$')
def isalnum_(s):
return alnum_Reg.match(s) is not None

#半角記号
symbolReg = re.compile(r'^[!-/:-@[-`{-~]+$')
def issymbol(s):
return symbolReg.match(s) is not None

#ASCII文字
asciiReg = re.compile(r'^[!-~]+$')
def isascii(s):
return asciiReg.match(s) is not None

isalnum('abc123') #--> True
isalnum(u'あいう') #--> False

※空白文字は False

※空文字列のときにも True を返したい場合は、正規表現の r'^[ ... ]+$'r'^[ ... ]*$' に変えてください

情報が少ない気がしたのでメモしておきます。


参考サイト


...

今回の件とは関係ないみたいですが、Google App Engine では Python3 は今の所使えません (Python 2.7まで) 。

なので、文字列が Unicode と str の2種類(正確にはバイト文字列も)あり不便です...。


追記

コメントにて指摘していただきました。

isalnum メソッドがうまく働かないのはunicode 文字列の場合のようです。

UTF8 にエンコードすると期待通りの動作をします。

isalnum メソッドの他に、isalpha (英字)、isdigit (数字)、islower (小文字)、isupper (大文字) を利用できます。

その他の判定(ASCII判定など)についてはメソッドがないので、本文の正規表現を使ってください。


Python 2.x の場合

str 文字列の場合は isalnum メソッドは正しく動作します。

ただ str 文字列で日本語などの全角文字を扱うと、文字数の取得などが思い通りにならないので unicode 文字列を使う方が便利です。

その時は str に変換して確かめます。

u'あいう'.encode('utf-8').isalnum()  #--> False


Python 3.x の場合

Python 3.x 系では str と unicode は統合され、str という名前ですが実態は unicode になっています。

その為、普通の文字列リテラルでも utf-8 にエンコードする必要があります。

'あいう'.encode('utf-8').isalnum()  #--> False

以上 追記