Pythonのsplit()メソッドは、文字列を特定の区切り文字で分割してリストを返す便利な機能です。ただし、標準のsplit()は1種類のseparatorしか指定できないため、カンマやセミコロン、空白類文字などが混在するデータを一度に分割することはできません。
なお、「1種類」とは「1文字」という意味ではなく、"<>"のような複数文字からなる1個のseparatorは指定できます。本記事で扱う「複数の区切り文字」は、カンマとセミコロンのように複数候補を同時に指定したいケースを指します。
この記事では、Pythonのsplitで複数の区切り文字を指定して分割する具体的な方法を、re.split()を中心に、実践的なサンプルコードとともに解説していきます。
Pythonのsplitで複数の区切り文字を指定して分割する方法
Pythonの標準split()メソッドは、separatorに単一の文字列のみを受け取り、複数候補を同時には扱えません。この点は公式ドキュメントにも明記されています。
The sep argument may consist of multiple characters as a single delimiter (to split with multiple delimiters, use re.split()).
出典:Python公式ドキュメント - str.split
上記の通り、複数候補の区切り文字で分割したい場合はre.split()の使用が公式に推奨されています。本記事では、re.split()を主な方法として紹介し、単純なケース向けの代替手段としてreplace()を組み合わせる方法も取り上げます。
- re.split()で正規表現を使って複数の区切り文字で分割する(公式推奨)
- replace()とsplit()を組み合わせて複数の区切り文字で分割する(単純なケース向け)
re.split()で正規表現を使って複数の区切り文字で分割する
re.split()は、Pythonの正規表現モジュールreに含まれる関数で、正規表現パターンに一致する箇所で文字列を分割します。正規表現とは、文字列のパターンを記述するための特殊な記法のことで、複数の文字をまとめて指定できます。
import re
text = "りんご,バナナ;みかん スイカ"
result = re.split(r"[,; ]", text)
print(result)
上記のコードでは、正規表現パターン[,; ](カンマ・セミコロン・半角スペース)を使って、いずれかの位置で文字列を分割しています。角括弧[]内に列挙した文字はOR条件として扱われるため、いずれか1文字に一致した箇所で分割が実行されます。実行結果は['りんご', 'バナナ', 'みかん', 'スイカ']です。
タブや改行も区切りに含めたい場合は、\s(スペース・タブ・改行などの空白類文字に一致するメタ文字)を使って[,;\s]と書けます。なお、正規表現パターンはr"..."のようにraw文字列で記述することが推奨されています。バックスラッシュを含むパターンで、Python文字列リテラルと正規表現の両方でエスケープが必要になる二重エスケープを避けられるためです。
re.split(pattern, string, maxsplit=0, flags=0) - Split string by the occurrences of pattern.
出典:Python公式ドキュメント - re.split
re.split()は区切り文字の種類が多い場合や、パターンが複雑な場合に適しています。なお、正規表現内で特別な意味を持つメタ文字(. * + ? ( ) [ ] { } \ | ^ $)を区切り文字として使う場合は、\でエスケープするか、文字クラス[]内に配置する必要があります。ハイフン-は文字クラス内では位置によって範囲指定の意味を持つため、文字クラスの先頭または末尾に置くと安全です。
replace()とsplit()を組み合わせて複数の区切り文字で分割する
replace()メソッドで複数の区切り文字を1種類に統一してから、split()で分割する方法です。正規表現を使わないため、reモジュールのインポートが不要で、単純な固定文字の置換で済むケースでは書きやすいことが多い方法です。
text = "りんご,バナナ;みかん スイカ"
for delimiter in [";", " "]:
text = text.replace(delimiter, ",")
result = text.split(",")
print(result)
上記のコードでは、セミコロンとスペースをカンマに置換してから、カンマで分割しています。実行結果は['りんご', 'バナナ', 'みかん', 'スイカ']です。
この方法を使う際は、統一先の文字(上記例のカンマ)が元の文字列に区切り文字以外の用途で含まれていないことを確認してください。意図しない位置で分割される原因になります。また、区切り文字の種類が増えるとreplace()の呼び出しが増えて可読性が下がるため、区切り候補が増えそうな場合はre.split()の使用を検討してください。
なお、区切り候補がすべて1文字ずつの場合は、str.translate()とstr.maketrans()を使う方法もあります。text.translate(str.maketrans({";": ",", " ": ","}))のように記述することによって、複数の文字を1回の呼び出しで置換できます。
ただし、str.translate()は1文字単位で変換表を適用する仕様のため、"<>"のような複数文字からなる区切り候補の正規化には使えません。その場合はreplace()の繰り返しかre.split()を使ってください。
splitで複数の区切り文字を使う際の注意点と対処法
複数の区切り文字で文字列を分割する場合、区切り文字が連続して出現するケースや、区切り文字自体を結果に残したいケースなど、想定外の結果が生じる場面があります。それぞれの対処法を把握しておくことによって、実際のデータ処理で予期しない結果を防ぐことができます。
連続する区切り文字による空文字列を除去する
re.split()で分割する際、区切り文字が連続して出現すると、分割結果に空文字列""が含まれます。
import re
text = "りんご,,バナナ; ;みかん"
result_with_empty = re.split(r"[,;\s]", text)
print(result_with_empty)
result_without_empty = re.split(r"[,;\s]+", text)
print(result_without_empty)
上記のコードでは、1つ目のre.split(r"[,;\s]", text)は['りんご', '', 'バナナ', '', '', 'みかん']のように空文字列が含まれる結果を返します。2つ目のre.split(r"[,;\s]+", text)は正規表現の+(直前の要素の1回以上の繰り返し)を使うことによって、連続する区切り文字をまとめて1つの区切りとして扱い、['りんご', 'バナナ', 'みかん']を返します。
パターンの変更が難しい場合は、リスト内包表記で空文字列を除去する方法もあります。[s for s in result if s]のように記述することによって、空文字列を含まないリストを生成できます。
なお、引用符やエスケープを含む本格的なCSVデータを扱う場合は、split系のメソッドではなくPython標準のcsvモジュールの使用を推奨します。splitでは引用符で囲まれた区切り文字を正しく扱えないためです。
区切り文字自体を結果に含めて分割する
re.split()では、正規表現パターンをキャプチャグループ(丸括弧)で囲むと、一致した区切り文字もグループとして結果に含まれます。キャプチャグループとは、正規表現のパターン内で丸括弧()で囲んだ部分のことで、一致した文字列を結果に保持する機能を持ちます。
import re
text = "100+200-300*400"
result = re.split(r"([+\-*])", text)
print(result)
上記のコードでは、パターン([+\-*])のように丸括弧で囲むことによって、区切り文字である演算子ぽ+んん、-、*)が分割結果に含まれます。実行結果は['100', '+', '200', '-', '300', '*', '400']です。式のトークン分割など、区切り文字そのものを後続処理で利用したい場面で役立ちます。
If there are capturing groups in the separator and it matches at the start of the string, the result will start with an empty string. The same holds for the end of the string.
出典:Python公式ドキュメント - re.split
キャプチャグループを使う場合、文字列の先頭や末尾が区切り文字で始まると、結果の先頭や末尾に空文字列が含まれる点に注意してください。また、空マッチ可能なパターンを使うとさらに挙動が複雑になります。不要な空文字列は、前述のリスト内包表記[s for s in result if s]で除去できます。
Pythonのsplitに関するよくある質問
split()で2文字以上の区切り文字(例:<>)を指定できますか?
はい、str.split()は1個のseparatorとして複数文字の文字列を受け取れます。"1<>2<>3".split("<>")のように記述すると['1', '2', '3']が得られます。一方、","と";"のような複数候補の区切り文字を同時に指定したい場合は、str.split()では直接扱えないため、re.split(r",|;", text)のようにパイプ記号|を使うか、文字クラス[,;]を使います。
splitの処理速度はre.splitとreplace+splitで違いますか?
処理速度は入力文字列の長さ、区切り文字の種類、Pythonの実装・バージョンなどに依存するため、一概にどちらが速いとは断定できません。速度がクリティカルな場面では、標準ライブラリのtimeitモジュールを使って、実際のデータに対して計測することを推奨します。
This module provides a simple way to time small bits of Python code.
出典:Python公式ドキュメント - timeit
※上記コンテンツの内容やソースコードはAIで確認・デバッグしておりますが、間違いやエラー、脆弱性などがある場合は、コメントよりご報告いただけますと幸いです。
ITやプログラミングに関するコラム
PythonをWebで実行する方法
共通テスト「情報Ⅰ」2年目で変わる、日本の教育と学び方
gitでブランチ(branch)を切り替える方法
git cloneでブランチを指定する方法
64GBのメモリが必要な人・不要な人の特徴
PCを再起動するコマンド一覧
CapsLock以外で大文字になる原因【Windows編】
パソコンで大文字になるのを解除する方法
面白いAIの活用事例を業界別に紹介
Gitでcommit(コミット)を取り消す方法
ITやプログラミングに関するニュース
サイボウズがkintone AIを正式提供、β版から約1年を経てクレジット制を導入
ロゼッタのラクヤクAIがCSRドラフト作成期間を90%以上短縮、従来4週間を約2日に
AI CROSSが不動産業界向け生成AI伴走支援を開始、アスコットの業務AI実装を実践サポート
日本情報クリエイトが「オーナー提案AIロボⅡ」売買査定を刷新、月1万円からW査定が回数無制限に
Wur株式会社がAI新規事業診断サービス「MVP事業診断レポート」をリリース、12の質問で事業構想を約10分で分析
バトンズがM&A専門家向け「AI概要書」β版を提供開始、企業概要書のドラフトを最速3分で自動生成
SCSKが観光DXサービス「Connexia」を開発、首里城公園でNFT活用の周遊促進が始動
Verdent AI発表、エンジニア不要でソフトウェアを構築する「AIエンジニアリングチーム」が登場
ゼネラルBREXAテクノロジーが外食・小売向けAIサービス「aimana」を開発、店長の意思決定をデータで支援
田中組がKencopa工程AIエージェント製品版を先行利用開始、建設現場の工程管理属人化を解消へ
