splitメソッドを使って文字列を空白文字や特定の文字列を区切りとして複数の文字列へと分割する方法を見ていく。似た処理を行うrstripメソッドとstliplinesメソッドも紹介。
この記事は会員限定です。会員登録(無料)すると全てご覧いただけます。
# 空白文字で分割
s1 = 'atmarkit deep\tinsider\nforum'
r = s1.split() # 区切りを指定しなければ、タブ、改行なども空白文字として扱われる
print(r) # ['atmarkit', 'deep', 'insider', 'forum']
# 指定した文字を区切りとする
s2 = 'kawasaki, isshiki, endo, shimada'
r = s2.split(',') # カンマ「,」を区切りに指定
print(r) # ['kawasaki', ' isshiki', ' endo', ' shimada']
r = s2.split(', ') # カンマ+空白文字を区切りに指定
print(r) # ['kawasaki', 'isshiki', 'endo', 'shimada']
# 分割回数を指定
r = s2.split(', ', 2) # 最大分割回数を2回と指定
print(r) # ['kawasaki', 'isshiki', 'endo, shimada']
# 改行文字で分割
r = s1.splitlines() # 改行箇所(\n)で分割
print(r) # ['atmarkit deep\tinsider', 'forum']
# 文字列右端から分割を行う
r = s2.rsplit(', ', 2) # ', 'を区切りとして、右端から分割。最大分割回数は2回
print(r) # ['kawasaki, isshiki', 'endo', 'shimada']
Pythonの文字列には、文字列を分割するメソッドとして以下が用意されている。
str.split(sep=None, maxsplit=-1)
str.rsplit(sep=None, maxsplit=-1)
str.splitlines([keepends])
以下ではこれらについて簡単にまとめる。
splitメソッドはパラメーターsepに指定した文字列を区切りとして、文字列を分割し、分割後の文字列を要素とするリストを返送する(sepに指定した文字列はリストには格納されない)。パラメーターmaxsplitには分割を最大で何回行うかを指定する。指定しなかった場合または-1を指定した場合には、パラメーターsepに指定した文字列がある限り、分割が行われる。分割は文字列の先頭(左端)から順番に行われる。
sepを指定しなかった場合には、Noneが与えられたものとして解釈される。このときには、連続する空白文字(半角空白文字、全角空白文字、タブ文字、改行文字など)を1つの区切り文字列として、文字列の分割が行われる。以下はその例だ。
s = 'abc def\t\tghi\njkl mno' # 半角空白、2つのタブ、改行、半角空白と全角空白
r = s.split()
print(r) # ['abc', 'def', 'ghi', 'jkl', 'mno']
上のコード例では、文字列sには空白文字として、順番に1個の半角空白文字、2個の連続するタブ文字、1個の改行文字、連続する半角空白文字と全角空白文字が含まれている。そして、sepを指定せずにsplitメソッドを呼び出している。その結果はコメントにも記したように、「['abc', 'def', 'ghi', 'jkl', 'mno']」というリストになる。連続する空白文字は1つの区切りとして扱われ、リストには連続するタブ文字で区切られた空文字列などが含まれていないことに注目しよう。上の例では示していないが、この形式でsplitメソッドを呼び出したとき、文字列の先頭と末尾に含まれる空白文字は無視される(リストには含まれない)。
一方、sepを指定した場合には、その文字列のみを区切りとして分割が行われる。「split(' ')」のような呼び出しは、半角空白文字のみを分割時の区切りとしてタブ文字などでは分割が行われない。以下に例を示す。
s = 'abc def\nghi'
r = s.split()
print(r) # ['abc', 'def', 'ghi']
r = s.split(' ')
print(r) # ['abc', 'def\nghi']
r = s.split('') # ValueError
この例では、文字列sには半角空白文字と改行文字が含まれている。そして、この文字列に対して、引数なしでsplitメソッドを呼び出し、次にsepに半角空白文字を指定してsplitメソッドを呼び出している。それらの結果が異なっている点に注意しよう。前者は改行文字がある箇所でも分割を行っているが、後者では分割が行われていない。なお、最後の例にあるようにsepに空文字列('')は渡せない。
また、sepを指定した場合には、文字列内でそれらが連続している箇所で、それらはひとまとまりの区切りとしては機能しない。このときには空文字列が指定した区切りの間にあるものとして扱われる。以下に例を示す。
s = '1,2,,4'
r = s.split(',')
print(r) # ['1', '2', '', '4']
この例では、連続するカンマ「,」が含まれる文字列に対して、区切り文字をカンマとしてsplitメソッドを呼び出しているが、このときには連続するカンマ「,,」の間には空文字列が含まれているものとして分割が行われる。そのため、返送されるのは4つの要素(うち、1つは空文字列)からなるリストとなっている(CSVファイルに格納される各行の分割ではこのような振る舞いが好ましいだろう)。
sepには複数の文字で構成される文字列を指定してもよい。そのときには、その文字列と完全に一致する部分で分割が行われる。以下に例を示す。
s = 'abc, def, ghi, jkl'
r = s.split(',')
print(r) # ['abc', ' def', ' ghi', ' jkl']:余計な空白入り
r = s.split(', ')
print(r) # ['abc', 'def', 'ghi', 'jkl']:空白を区切りに含めることで対処
この例では、カンマで要素を区切っているように見えるが、その後には半角空白文字が挿入されている。そのため、区切りをカンマのみとして分割を行うと不要な半角空白文字が含まれてしまう。そこで、区切りをカンマと半角空白文字とすることで、うまいこと文字列から要素を取り出せる(空白文字が含まれていたり含まれていなかったりするときには、replaceメソッドでそれを削除してから、splitメソッドを呼び出すといった方法が考えられる)。
最大の分割回数を指定するmaxsplitを指定しなければ、既に述べたように区切りが見つかっただけ分割が行われる。指定すれば、最大でその回数だけ分割が行われる。以下に例を示す。
s = 'abc:def:ghi:jkl'
r = s.split(':', 2)
print(r) # ['abc', 'def', 'ghi:jkl']
最後に空文字列を分割しようとしたときの振る舞いについても取り上げておこう。空文字列に対して、sepを指定してsplitメソッドを呼び出すと空文字列を含んだリストが返送される。これに対して、sepを指定せずにsplitメソッドを呼び出すと空のリストが返送される。わずかな差だが、場合によってはハマるかもしれないので念のため記しておく。
s = ''
r = s.split('a')
print(r) # ['']
r = s.split()
print(r) # []
空文字列を要素とするリストは真であり、空のリストは偽である。この差が何らかの条件分岐やテストでプログラムの振る舞いに影響を与えるかもしれない。
rsplitメソッドは分割を文字列の末尾(右端)から行うことを除けば、splitメソッドと同様な処理を行う。以下では簡単な例だけを示しておこう。
s = 'abc def\tghi jkl, mno'
r = s.rsplit()
print(r) # ['abc', 'def', 'ghi', 'jkl,', 'mno']
r = s.rsplit('\t')
print(r) # ['abc def', 'ghi jkl, mno']
r = s.rsplit(' ', 2)
print(r) # ['abc def\tghi', 'jkl,', 'mno']
上記例から分かると思うが、splitメソッドとrsplitメソッドで差が出るのは、maxsplitに1以上の値を指定した(かつ、指定した値よりもたくさんの区切りが文字列に含まれている)ときだ。最後の例ではmaxsplitに2を指定しているが、分割が文字列の末尾から行われている点に注目してほしい。
splitメソッドとrsplitメソッドは、特定の区切り文字で文字列を分割するものだったが、分割箇所を改行文字だけとして、複数行を格納する文字列を行ごとに分割するのがsplitlinesメソッドだ。これは改行文字として改行(\n)に加えて、復帰(\r)、改行+復帰(\r\n)などを認識する。詳細についてはPythonのドキュメント「str.splitlines」を参照されたい。
以下に例を示す。
s = 'abc\n\ndef\nghi\n'
r = s.splitlines()
print(r) # ['abc', '', 'def', 'ghi']
r = s.split('\n')
print(r) # ['abc', '', 'def', 'ghi', '']
r = s.split()
print(r) # ['abc', 'def', 'ghi']
この例では、文字列中およびその末尾に改行文字が含まれている。これに対して、splitlinesメソッドとsplitメソッドを呼び出している。splitlinesメソッドでは文字列末尾の改行文字は無視して、リスト末尾の要素として空文字列が追加されていない点に注目しよう。これに対して、sepに改行文字を指定して、splitメソッドを呼び出した場合、文字列中の連続する改行文字についてはsplitlinesメソッドと同様に空文字列を取り出しているが、文字列末尾の改行文字についても空文字列を取り出している。さらに、引数なしでsplitメソッドを呼び出すと、(既に述べたように)連続する改行文字は1つにまとめられることから、また末尾の空白文字(改行文字)は無視されることから、返送されるリストには空文字列が全く含まれない。
このようにsplitlinesメソッドとsplitメソッドでその挙動に差が出ることがあるので、それぞれの状況に適切な方法を選ぶようにしよう。
Copyright© Digital Advantage Corp. All Rights Reserved.