0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

その文字列処理、import reしなくても標準ライブラリだけで書けます

0
Posted at

その文字列処理、import reしなくても標準ライブラリだけで書けます

「前後の文字列を切り出したい」「特定の接頭辞を取り除きたい」となると、反射的に import re して正規表現を書き始めていませんか?

実は簡単な文字列操作であれば、Python標準の str メソッドだけで、正規表現より読みやすく書けることが多くあります。

本記事はPython公式ドキュメント(文字列メソッド、PEP 616)をもとに、2026年9月時点で最新のPython 3.14系を基準にしています。

接頭辞・接尾辞の削除にはremoveprefix/removesuffix

ファイル名から拡張子だけ取りたい、URLからプロトコル部分だけ取りたい、というときによく見るのが以下のような正規表現です。

import re

url = "https://example.com"
domain = re.sub(r"^https://", "", url)

これは str.removeprefix() を使うだけで、正規表現なしで書けます。

url = "https://example.com"
domain = url.removeprefix("https://")
print(domain)
# example.com

同様に、末尾を取り除きたい場合は str.removesuffix() を使います。

filename = "report.txt"
name = filename.removesuffix(".txt")
print(name)
# report

removeprefix() と removesuffix() はPython 3.9で追加されたメソッドです(PEP 616)。Python 3.8以前の環境で動かす必要があるコードでは使えないため、startswith() と文字列スライスを組み合わせた書き方に置き換える必要があります。

似たメソッドに strip() がありますが、こちらは「指定した文字の集合」を端から削っていく仕様のため、複数文字からなる接頭辞・接尾辞の削除には向きません。

たとえば "xxprefix".strip("x") のように、意図せず余分な文字まで削れてしまうことがあります。

ピンポイントに1つの文字列を取り除きたい場合は、removeprefix() / removesuffix() のほうが安全です。

区切り文字での分割にはpartition

「最初に出てきた = の前後で分割したい」というケースで、re.split を使っている例もよく見かけます。

import re

line = "name=Alice=Bob"
key, value = re.split(r"=", line, maxsplit=1)

これは str.partition() で置き換えられます。

line = "name=Alice=Bob"
key, sep, value = line.partition("=")
print(key)   # name
print(value) # Alice=Bob

partition() は「区切り文字より前」「区切り文字そのもの」「区切り文字より後ろ」の3つをタプルで返します。

区切り文字が見つからなかった場合でも例外にはならず、(元の文字列, "", "") が返るため、try/except で囲む必要がないのも扱いやすい点です。

末尾から分割したい場合は rpartition() を使うと、最後に出てきた区切り文字を基準に分割できます。

path = "/var/log/app/error.log"
_, _, filename = path.rpartition("/")
print(filename)
# error.log

ワイルドカードでのパターンマッチにはfnmatch

*.log のような、シェルでおなじみのワイルドカード形式でファイル名を判定したいだけなのに、わざわざ正規表現に変換して書いているケースもあります。

import re

pattern = re.compile(r".*\.log$")
if pattern.match("error.log"):
    print("matched")

このような単純なワイルドカードでの判定は、標準ライブラリの fnmatch モジュールで十分です。

import fnmatch

if fnmatch.fnmatch("error.log", "*.log"):
    print("matched")

fnmatch.fnmatch() は *(任意の文字列)や ?(任意の1文字)といった、シェルのワイルドカードと同じ記法をそのまま使えます。

正規表現の特殊文字(. や \ など)を意識する必要がない分、ファイル名のパターンマッチのような用途では読みやすさが上がります。

使い分けの目安

すべてを標準の文字列メソッドに寄せるべきというわけではなく、向き不向きがあります。

やりたいこと 向いている方法
決まった接頭辞・接尾辞の削除 removeprefix() / removesuffix()
1つの区切り文字での分割 partition() / rpartition()
ワイルドカード形式でのファイル名判定 fnmatch
桁数や文字種を条件にした複雑なパターン抽出 re
複数のパターンを組み合わせた判定 re

「見つけたい文字列の形」が具体的に1つに決まっているなら標準メソッドで書けることが多く、「数字が2〜4桁」「英数字とハイフンの組み合わせ」のように条件が抽象的になるほど、正規表現の出番になってくるという感覚で使い分けると判断しやすいです。

まとめ

  • 接頭辞・接尾辞の削除は removeprefix() / removesuffix()(Python 3.9以降)で正規表現なしに書ける
  • 1つの区切り文字での分割は partition() / rpartition() が例外を気にせず使えて扱いやすい
  • ワイルドカード形式のパターンマッチは fnmatch モジュールで十分なことが多い
  • パターンが具体的なら標準メソッド、条件が抽象的になってきたら正規表現、という基準で使い分ける

正規表現が悪いわけではありませんが、単純な処理にまで持ち出すと、あとから読む人にとって「なぜここまで複雑な書き方をしているのか」と余計な負担をかけてしまいます。

次に文字列処理を書くときは、一度標準メソッドで足りないか確認してみてください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?