正規表現の道を行き過ぎる前に、 ast.literal_evalの使用を検討しましたか?
例:
In [35]: ast.literal_eval('1')
Out[35]: 1
In [36]: type(ast.literal_eval('1'))
Out[36]: int
In [38]: type(ast.literal_eval('1.0'))
Out[38]: float
In [40]: type(ast.literal_eval('[1,2,3]'))
Out[40]: list
Python を使用して解析することもできます。
OK、これはより大きな例です:
import ast, re
def dataType(str):
str=str.strip()
if len(str) == 0: return 'BLANK'
try:
t=ast.literal_eval(str)
except ValueError:
return 'TEXT'
except SyntaxError:
return 'TEXT'
else:
if type(t) in [int, long, float, bool]:
if t in set((True,False)):
return 'BIT'
if type(t) is int or type(t) is long:
return 'INT'
if type(t) is float:
return 'FLOAT'
else:
return 'TEXT'
testSet=[' 1 ', ' 0 ', 'True', 'False', #should all be BIT
'12', '34l', '-3','03', #should all be INT
'1.2', '-20.4', '1e66', '35.','- .2','-.2e6', #should all be FLOAT
'10-1', 'def', '10,2', '[1,2]','35.9.6','35..','.']
for t in testSet:
print "{:10}:{}".format(t,dataType(t))
出力:
1 :BIT
0 :BIT
True :BIT
False :BIT
12 :INT
34l :INT
-3 :INT
03 :INT
1.2 :FLOAT
-20.4 :FLOAT
1e66 :FLOAT
35. :FLOAT
- .2 :FLOAT
-.2e6 :FLOAT
10-1 :TEXT
def :TEXT
10,2 :TEXT
[1,2] :TEXT
35.9.6 :TEXT
35.. :TEXT
. :TEXT
そして、同じ結果を生成する正規表現ソリューションが確実に必要な場合は、次のとおりです。
def regDataType(str):
str=str.strip()
if len(str) == 0: return 'BLANK'
if re.match(r'True$|^False$|^0$|^1$', str):
return 'BIT'
if re.match(r'([-+]\s*)?\d+[lL]?$', str):
return 'INT'
if re.match(r'([-+]\s*)?[1-9][0-9]*\.?[0-9]*([Ee][+-]?[0-9]+)?$', str):
return 'FLOAT'
if re.match(r'([-+]\s*)?[0-9]*\.?[0-9][0-9]*([Ee][+-]?[0-9]+)?$', str):
return 'FLOAT'
return 'TEXT'
ただし、ast バージョンよりも正規表現をお勧めすることはできません。正規表現で解釈するのではなく、これらのデータ型が何であるかをPythonに解釈させてください...