Python で camel case → snake case もネット検索するとたくさん方法が紹介されてる。
しかし、よく紹介されてる方法は、本当に期待どおりか疑問がのこる。
# -*- coding: UTF-8 -*- import re str = "abcDefGhi2j" str2 = "AbcDefGhi2j" res = re.sub("([A-Z])",lambda x:"_" + x.group(1), str).lower() res2 = re.sub("([A-Z])",lambda x:"_" + x.group(1), str2).lower() print("%s → %s" % (str , res)) print("%s → %s" % (str2, res2))
結果は、、
abcDefGhi2j → abc_def_ghi2j AbcDefGhi2j → _abc_def_ghi2j
2番目、str2 の "A"が、"_a" になってしまう。これを "a" にする方法は、
大文字1文字正規表現ではなく、任意1文字+大文字1文字で処理する方法にすることだ。
res2 = re.sub("(.[A-Z])",lambda x:x.group(1)[0] + "_" +x.group(1)[1], str2).lower() print("%s → %s" % (str2, res2))
結果、、
AbcDefGhi2j → abc_def_ghi2j
ラムダなんて使わない方法では、、
res2 = re.sub('([a-z0-9])([A-Z])', r'\1_\2', re.sub('(.)([A-Z][a-z]+)', r'\1_\2', str2)).lower()
という手段もある。
変換後の snake case 文字列が全て小文字か?大文字か?どちらが良いか選択できる
方が良いので、メソッド化する。
def toSnakeCase(string, upper=False): import re if upper: return re.sub("(.[A-Z])", lambda x: x.group(1)[0] + "_" + x.group(1)[1], string).lower().upper() else: return re.sub("(.[A-Z])", lambda x:x.group(1)[0] + "_" +x.group(1)[1], string).lower()
第2引数=True なら、結果全て大文字だ。
res = toSnakeCase(str2, True) print("%s → %s" % (str2 , res))
結果、、
AbcDefGhi2j → ABC_DEF_GHI2J