文字列が提供する各種メソッドを使って、指定した文字(文字列)の前後を抽出する方法を紹介。正規表現を使うシンプルな例も取り上げる。
* 本稿は2021年03月23日に公開された記事をPython 3.12.0で動作確認したものです(確認日:2023年10月04日)。
# スライスを用いて特定の文字より後ろを抽出
s = '2021/03/23 05:30'
target = ' '
idx = s.find(target)
r = s[idx+1:] # スライスで半角空白文字のインデックス+1以降を抽出
print(r) # 05:30
# スライスを用いて特定の文字より前を抽出(特定の文字以降を削除)
s = '2021/03/23 05:30'
target = ' '
idx = s.find(target)
r = s[:idx] # スライスで半角空白文字よりも前を抽出
print(r) # 2021/03/23
# findメソッドに2文字以上の文字列を渡す例
s = 'date: 2021/03/23, time: 05:30'
target = 'time: ' # 「time: 」より後ろ(時刻)を抽出したい
idx = s.find(target)
r = s[idx+len(target):]
print(r) # 05:30
# splitメソッドを使ってもよい
s = '2021/03/23 05:30'
sep = ' '
t = s.split(sep) # 半角空白文字で文字列を分割
r = t[0] # 日付はインデックス0に含まれている
print(r) # 2021/03/23(特定の文字より前を抽出=特定の文字以降を削除)
r = t[1] # 時間はインデックス1に含まれている
print(r) # 05:30(特定の文字より後ろを抽出=特定の文字までを削除)
# partitionメソッドを使う方法もある
sep = ' '
t = s.partition(' ') # 戻り値は(sepよりも前, sep, sepよりも後ろ)というタプル
r = t[0] # 日付はインデックス0に含まれている
print(r) # 2021/03/23(特定の文字より前を抽出=特定の文字以降を削除)
r = t[2] # 時間はインデックス2に含まれている
print(r) # 05:30(特定の文字より後ろを抽出=特定の文字までを削除)
# 正規表現を使って特定の文字(文字列)より後ろにある特定のパターンを抽出
import re
s = 'date: 2021/03/23, time: 05:30'
p = r'time: (.*)' # 「time: 」の後ろにある時間だけを抽出したい
m = re.search(p, s)
print(m.group(1)) # 05:30
p = r'date: (.*),' # 「date: 」の後ろにある日付だけを抽出したい
m = re.search(p, s)
print(m.group(1)) # 2021/03/23
p = r': ([\d:/]+)' # コロンの後ろにある日付と時刻を抽出したい
r = re.findall(p, s)
print(r)
一定の形式で記述されている文字列から、必要な部分だけを取り出したいということはよくあるだろう。空白文字「 」やコロン「:」などの記号に続けて何らかのデータが記述されている場合が例として考えられる。単純な場合は、正規表現を使わずとも文字列のメソッドとスライスを使うだけでそれらを抽出できる。
以下に例を示す。ここでは「'2021/03/23 05:30'」という半角空白文字を挟んで日付と時刻が記述されている文字列を例とする(以下で使用しているfindメソッドは引数に指定した文字列が見つからないときには-1を返す。本来はこの値をチェックして、処理を分岐させるべきだが、ここでは省略する。また、文字列のindexメソッドを使っても同様に指定した文字のインデックスが得られるが、こちらは指定した文字列が見つからないときにはValueError例外となる)。
s = '2021/03/23 05:30'
target = ' '
idx = s.find(target) # 半角空白文字のインデックスを検索
r = s[idx+1:] # スライスで半角空白文字のインデックス+1以降を抽出
# 見つからなかったときを考慮:「r = s[idx+1:] if idx != -1 else 'not found'」
print(r) # 05:30
この文字列から時刻だけを取り出すのであれば、文字列のfindメソッドを用いて、空白文字が格納されているインデックスを調べ、「文字列[空白文字のインデックス+1:]」のようにして、指定した文字よりも右側を抽出すればよい。この場合は特定の文字を抽出する文字列に含みたくないのでfindメソッドで得たインデックスに1を加算しているが、findメソッドに渡した文字を含めて抽出したければ、インデックスはそのままでよい。
特定の文字より後ろを取り出すのではなく、それよりも前の部分を抽出するには「文字列[:不要な部分の先頭のインデックス]」とする。以下はその例だ(対象の文字列は最初の例と同じく「'2021/03/23 05:30'」とする)。
s = '2021/03/23 05:30'
target = ' '
idx = s.find(target)
r = s[:idx] # スライスで半角空白文字よりも前を抽出
print(r) # 2021/03/23
ここで覚えておきたいのは、文字列を抽出するとは、それ以外の部分を削除することに他ならないということだ。最初の例は「半角文字列までを削除する」とも考えられるし、上の例は「半角文字列以降を削除する」とも考えられる。
findメソッドには1文字だけではなく、任意の長さの文字列を渡してもよい。以下の例は最初の例よりは複雑な「'date: 2021/03/23, time: 05:30'」という文字列から時刻だけを抽出しようというものだ。
s = 'date: 2021/03/23, time: 05:30'
target = 'time: ' # 「time: 」より後ろ(時刻)を抽出したい
idx = s.find(target)
r = s[idx+len(target):]
print(r) # 05:30
時刻を取得したいので、ここでは単独のコロン「:」や半角空白文字ではなく、より明確に「'time: '」を引数としてfindメソッドを呼び出している(コロンの後に半角空白文字が含まれている点に注意)。findメソッドの戻り値は「'time: '」の「't'」があるインデックスとなるので、これに「time: 」の長さを含めて、文字列をスライスすることで望みの結果が得られる。
これまでに見てきた方法で「'date: '」に続く日付を抽出するには、少し面倒くさくなる。こうしたときには、本稿最後に示すように正規表現を使った方がよいかもしれない。
s = 'date: 2021/03/23, time: 05:30'
target1 = 'date: ' # 「date: 」の後にある日付を抽出したい
idx1 = s.find(target1)
target2 = ','
idx2 = s.find(target2)
r = s[idx1+len(target1):idx2]
print(r) # 2021/03/23
同様なことは文字列のsplitメソッドを使っても行える。splitメソッドは引数に渡した文字列を区切りとして、文字列を区切っていく(このときには分割を行う回数も指定できるが、ここでは説明は省略する。詳細は「Python入門」の「文字列の操作」にある「文字列の分割:splitメソッド」を参照のこと)。
以下に例を示す。
s = '2021/03/23 05:30'
sep = ' '
t = s.split(sep) # 半角空白文字で文字列を分割
r = t[0] # 日付はインデックス0に含まれている
print(r) # 2021/03/23(特定の文字より前を抽出=特定の文字以降を削除)
r = t[1] # 時刻はインデックス1に含まれている
print(r) # 05:30(特定の文字より後ろを抽出=特定の文字までを削除)
この例では、半角文字列を区切りとして、日付と時刻を含んだ文字列を分割している。この結果は文字列リストであり、その先頭要素が日付、次の要素が時刻となる。そのため、前者を取得すれば元の文字列から日付を、後者を取得すれば元の文字列から時刻を取得したことになる。
さらに文字列のpartitionメソッドを使うことも考えられる。このメソッドは引数に指定した文字列を区切り文字として、元の文字列内でその区切りが最初に登場する箇所で文字列を分割する。戻り値は「(区切りよりも前の部分, 区切り, 区切りよりも後ろの部分)」という3要素のタプルとなる。
sep = ' '
t = s.partition(' ') # 戻り値は(sepよりも前, sep, sepよりも後ろ)というタプル
r = t[0] # 日付はインデックス0に含まれている
print(r) # 2021/03/23(特定の文字より前を抽出=特定の文字以降を削除)
r = t[2] # 時間はインデックス2に含まれている
print(r) # 05:30(特定の文字より後ろを抽出=特定の文字までを削除)
上記のメソッド(やスライス)では簡単に文字列を抽出できないこともあるかもしれない。そうした場合には、正規表現を使うことになるだろう。これについては別稿で詳しく解説するとして、簡単な例を以下に示すだけとしておく。
import re
s = 'date: 2021/03/23, time: 05:30'
p = r'time: (.*)' # 「time: 」の後ろにある時間だけを抽出したい
m = re.search(p, s)
print(m.group(1)) # 05:30
p = r'date: (.*),' # 「date: 」の後ろにある日付だけを抽出したい
m = re.search(p, s)
print(m.group(1)) # 2021/03/23
p = r': ([\d:/]+)' # コロンの後ろにある日付と時刻を抽出したい
r = re.findall(p, s)
print(r) # ['2021/03/23', '05:30']
Copyright© Digital Advantage Corp. All Rights Reserved.