閉じる

【Python】文字列が特定の文字で始まる/終わるかを判定する

文字列の先頭や末尾が特定の文字列と一致するかを判定する処理は、ファイル拡張子やURLチェックなど実務で頻出します。

本記事ではPythonのstr.startswithstr.endswithの使い方を、基本から現場で役立つコツまで段階的に解説します。

空文字との関係や大文字小文字の無視、範囲指定や複数候補の同時判定など、つまずきやすいポイントも丁寧に補足します。

先頭・末尾判定の基本(Python)

文字列の先頭/末尾を判定するメソッド(startswith, endswith)

Pythonの文字列は、先頭一致判定にstartswith、末尾一致判定にendswithを備えています。

どちらも対象となる文字列(プレフィックス/サフィックス)を受け取り、一致すればTrue、一致しなければFalseを返します。

特に複数候補をまとめて判定できるタプル指定と、一部範囲だけを対象にするstart/end引数がポイントです。

返り値の型と基本ルール(”は常にTrue)

返り値はブール型boolです。

Pythonでは空文字''はあらゆる文字列の先頭かつ末尾に存在するというルールがあり、以下はすべてTrueになります。

逆に、()(空タプル)を渡した場合は一致候補が無いためFalseです。

Python
# 基本ルールの確認
s1 = "Python"
s2 = ""

print(s1.startswith(""))   # 空文字は常に先頭一致
print(s1.endswith(""))     # 空文字は常に末尾一致
print(s2.startswith(""))   # 空文字列に対しても同様
print(s2.endswith(""))

# 空タプルは候補が無いのでFalse
print(s1.startswith(()))
print(s1.endswith(()))
実行結果
True
True
True
True
False
False

以下はstartswith/endswithのインターフェイス要点です。

  • 書式: str.startswith(prefix[, start[, end]]) / str.endswith(suffix[, start[, end]])
  • prefix/suffix: 文字列、または文字列タプル
  • start/end: スライス同様に[start:end]の範囲で判定(終端は非包含)

表に主要ルールをまとめます。

観点ルール
返り値bool
空文字''先頭/末尾ともに常にTrue
複数候補タプルのみ可。リストは不可
空タプル()一致候補なしのためFalse
範囲指定start含む、endは含まない
大文字小文字無視メソッド引数では不可。casefold()等で事前変換

startswithで先頭を判定する

基本構文とサンプルコード

startswithは文字列が特定の接頭辞で始まるかを判定します。

可読性が高く、スライス比較より意図が明確です。

Python
# startswith の基本
lang = "Python 3.12"

print(lang.startswith("Py"))     # "Py"で始まるか
print(lang.startswith("Python")) # 完全一致の先頭
print(lang.startswith("Java"))   # 不一致
実行結果
True
True
False

複数パターンをまとめて判定する(tuple)

複数の接頭辞候補がある場合はタプルでまとめられます。

リストは使用不可で、TypeErrorになります。

Python
# 複数候補をタプルで
name = "readme.txt"

print(name.startswith(("read", "doc", "note")))  # いずれかに一致すればTrue

# リストを渡すとTypeError
try:
    print(name.startswith(["read", "doc"]))
except TypeError as e:
    print(f"Error: {e}")
実行結果
True
Error: startswith first arg must be str or a tuple of str, not list

一部だけを判定する(start/end引数)

start/endはスライスと同じ意味で、対象範囲を限定できます。

Python
# 範囲を限定して先頭一致を判定
text = "HelloWorld"

# インデックス5からの部分文字列は "World"
print(text.startswith("World", 5))            # True

# 0〜5の範囲("Hello")の中で"Hel"で始まるか
print(text.startswith("Hel", 0, 5))           # True

# endは非包含。0〜4("Hell")には"Hello"は収まらない
print(text.startswith("Hello", 0, 4))         # False
実行結果
True
True
False

大文字小文字を無視して判定する(casefold)

startswith自体に大文字小文字を無視するオプションはありません。

文字列同士をcasefold()で正規化してから判定します。

lower()よりcasefold()のほうが国際化対応として望ましいです。

Python
# 大文字小文字を無視した先頭一致
s = "Straße in Berlin"   # ß を含む
prefix = "STRASSE"       # 大文字

print(s.casefold().startswith(prefix.casefold()))  # True

# 複数候補にも対応する小ヘルパー
def startswith_icase(s: str, prefixes) -> bool:
    if isinstance(prefixes, tuple):
        folded = tuple(p.casefold() for p in prefixes)
        return s.casefold().startswith(folded)
    return s.casefold().startswith(prefixes.casefold())

print(startswith_icase("Hello", ("he", "yo")))     # True
print(startswith_icase("data.csv", ("JSON", "CSV")))  # False
実行結果
True
True
False

endswithで末尾を判定する

基本構文とサンプルコード

endswithは文字列が特定の接尾辞で終わるかを判定します。

ファイル拡張子のチェックなどで多用します。

Python
# endswith の基本
path = "archive.tar.gz"

print(path.endswith(".gz"))    # True
print(path.endswith(".zip"))   # False
実行結果
True
False

複数パターンをまとめて判定する(tuple)

複数の拡張子や接尾辞をまとめてチェックできます。

Python
filename = "report.final.pdf"

# 複数拡張子に対応
print(filename.endswith((".pdf", ".docx", ".xlsx")))  # True

# 空タプルはFalse
print(filename.endswith(()))  # False
実行結果
True
False

一部だけを判定する(start/end引数)

末尾判定でもstart/endで範囲を限定できます。

Python
# 範囲を限定して末尾一致
msg = "INFO: job done OK"

# 6〜の部分("job done OK")が"OK"で終わるか
print(msg.endswith("OK", 6))           # True

# 6〜14("job done")は"OK"で終わらない
print(msg.endswith("OK", 6, 14))       # False
実行結果
True
False

大文字小文字を無視して判定する(casefold)

こちらもcasefold()で正規化してから判定します。

Python
# 大文字小文字を無視した末尾一致
s = "README.TXT"
print(s.casefold().endswith(".txt"))  # ".txt"をそのまま小文字で渡してもOK

# 複数候補
def endswith_icase(s: str, suffixes) -> bool:
    if isinstance(suffixes, tuple):
        folded = tuple(x.casefold() for x in suffixes)
        return s.casefold().endswith(folded)
    return s.casefold().endswith(suffixes.casefold())

print(endswith_icase("photo.JPEG", (".jpg", ".jpeg", ".png")))  # True
実行結果
True
True

よくある用途と注意点

ファイル拡張子チェックに使う(.txtや.csv)

拡張子のように「末尾が特定の文字列か」を確認する処理ではendswithが最適です。

複数拡張子をまとめて許容する場合はタプル指定にすることで、分岐を増やさずに書けます。

大小文字を無視したいときはcasefold()を使います。

Python
files = ["data.csv", "image.PNG", "readme.md", "report.CSV"]

allow = (".csv", ".tsv")
for f in files:
    if f.casefold().endswith(tuple(ext.casefold() for ext in allow)):
        print(f"tabular: {f}")
    else:
        print(f"skip:    {f}")
実行結果
tabular: data.csv
skip:    image.PNG
skip:    readme.md
tabular: report.CSV

複合拡張子.tar.gzなども、(".gz", ".bz2")のようにまとめれば対応できます。

パス解析が必要なら別記事で扱うpathlibの利用も検討してください。

URLのスキームやドメインで判定(http, https)

URLのスキーム確認にはstartswith(("http://", "https://"))が読みやすいです。

ドメイン末尾のTLD判定にはendswith((".com", ".co.jp"))が使えます。

ただしフィッシング対策など厳密な検証が必要な場合は、ドット区切りやポート、パスの検証を含めたパーサの利用をおすすめします。

Python
urls = ["https://example.com", "http://localhost:8000", "ftp://files.example.org"]

for u in urls:
    if u.startswith(("http://", "https://")):
        print(f"web:  {u}")
    else:
        print(f"skip: {u}")
実行結果
web:  https://example.com
web:  http://localhost:8000
skip: ftp://files.example.org

スライス比較よりstartswith/endswithが可読的

s[:3] == "abc"のようなスライス比較でも先頭判定は可能ですが、startswith/endswithは「何をしたいか」が直感的で、複数候補や範囲指定も一貫した書式で表現できます

また、スライスは自分で長さを数える必要があり、意図が曖昧になりがちです。

Python
s = "abcXYZ"

# 可読性の比較
print(s.startswith("abc"))   # 意図が明確
print(s[:3] == "abc")        # 動作は同じだが意図がやや不透明
実行結果
True
True

複数条件はtupleのみ(listは不可)

候補の並びをlistで渡すとTypeErrorになります。

忘れずにtupleを使ってください。

tuple([...])で変換しても構いません。

Python
candidates = ["pre", "head"]
s = "prefix"

try:
    print(s.startswith(candidates))  # NG
except TypeError:
    print(s.startswith(tuple(candidates)))  # OKにしてから実行
実行結果
True

空白や改行が混ざる場合の前処理の考え方

入力値の前後に空白や改行が混ざると意図せぬ不一致になります。

判定前にstrip()lstrip()/rstrip()で前処理すると堅牢です。

全角空白や特殊空白が来る可能性がある場合は、追加の正規化(例えばunicodedata.normalizeの活用)も検討してください。

Python
raw = "  hello.txt \n"

clean = raw.strip()  # 前後の空白と改行を除去
print(clean.endswith(".txt"))  # True
実行結果
True

正規表現を使うべきケースとの使い分け(re)

startswith/endswithは固定の接頭辞・接尾辞に最適です。

一方でワイルドカードや桁数条件、文字クラスなど可変条件が必要な場合はreを使います。

先頭/末尾は^/$で表現できます。

Python
import re

s1 = "USER-12345"
s2 = "user_987"

# "USER-"で始まり、後に数字が続く
print(bool(re.match(r"^USER-\d+$", s1)))  # True

# 先頭は"USER-"ではないのでFalse
print(bool(re.match(r"^USER-\d+$", s2)))  # False

# 大文字小文字を無視
print(bool(re.match(r"^user_\d+$", s2, flags=re.IGNORECASE)))  # True
実行結果
True
False
True

使い分けの目安として、固定の「始まる/終わる」だけならstartswith/endswithパターンが複雑ならreと覚えると良いでしょう。

まとめ

本記事では、文字列のstartswithendswithの基本から応用までを解説しました。

空文字は常に一致、複数候補はタプルのみ、範囲は[start:end]、大文字小文字はcasefold()で正規化という要点を押さえれば、多くの場面で迷わず書けます。

拡張子やURLスキームのチェック、前処理としてのstrip()、複雑な条件ではreといった使い分けを意識し、意図が伝わる可読的なコードを心がけてください。

この記事を書いた人
エーテリア編集部
エーテリア編集部

人気のPythonを初めて学ぶ方向けに、文法の基本から小さな自動化まで、実際に手を動かして理解できる記事を書いています。

クラウドSSLサイトシールは安心の証です。

URLをコピーしました!