從字串右側(末尾)向左搜尋子字串最後出現位置,是解析路徑、檔名、日誌時間戳等場景的常見需求。Python rfind() 方法提供此功能:回傳子字串最後一次出現的索引,找不到回傳 -1(不拋出例外)。本文詳細說明語法、參數、與 find() 差異、邊界處理與實戰應用。
str.rfind(sub[, start[, end]])
#!/usr/bin/python3
# 範例 1:基本用法
s = "this is really a string example....wow!!!"
sub = "is"
print(s.rfind(sub)) # 5(最後一個 "is" 位置)
print(s.find(sub)) # 2(第一個 "is" 位置)
# 範例 2:指定搜尋範圍
print(s.rfind(sub, 0, 10)) # 5(索引 0-9 範圍內最後一個)
print(s.rfind(sub, 10, 0)) # -1(start > end,空範圍)
print(s.find(sub, 0, 10)) # 2
print(s.find(sub, 10, 0)) # -1
# 範例 3:找不到回傳 -1
print(s.rfind("xyz")) # -1
print(s.find("xyz")) # -1
# 範例 4:空字串搜尋(特殊行為)
print(s.rfind("")) # len(s)(空字串視為在末尾)
print(s.find("")) # 0(空字串視為在開頭)
# 範例 5:重疊匹配
s2 = "aaaa"
print(s2.rfind("aa")) # 2(非重疊,最後位置 2-3)
print(s2.find("aa")) # 0
| 方法 | 搜尋方向 | 找不到行為 | 回傳值 |
|---|---|---|---|
| find() | 左→右(第一個) | 回傳 -1 | 索引 |
| rfind() | 右→左(最後一個) | 回傳 -1 | 索引 |
| index() | 左→右(第一個) | 拋出 ValueError | 索引 |
| rindex() | 右→左(最後一個) | 拋出 ValueError | 索引 |
選擇建議: 不確定是否存在用 find/rfind;確定存在或視缺失為錯誤用 index/rindex。
s = "abcdefghijklmnop"
# 索引: 0123456789...
print(s.rfind("c", 0, 5)) # 2(搜尋 "abcde")
print(s.rfind("c", 5, 0)) # -1(start > end,空範圍)
print(s.rfind("c", 5)) # -1(搜尋 "fghijklmnop",無 c)
print(s.rfind("c", -5)) # -1(負索引:從倒數第5開始,即 "lmnop")
# 負索引支援(Python 切片語意)
print(s.rfind("k", -10)) # 10(從倒數第10字元開始搜尋)
def parse_path(path):
# 最後一個斜線後為檔名
last_slash = path.rfind("/")
if last_slash == -1:
filename = path
else:
filename = path[last_slash + 1:]
# 最後一個點為副檔名分隔
last_dot = filename.rfind(".")
if last_dot == -1:
name, ext = filename, ""
else:
name, ext = filename[:last_dot], filename[last_dot+1:]
return {"filename": filename, "name": name, "ext": ext}
print(parse_path("/home/user/document.pdf"))
# {'filename': 'document.pdf', 'name': 'document', 'ext': 'pdf'}
print(parse_path("data.csv"))
# {'filename': 'data.csv', 'name': 'data', 'ext': 'csv'}
print(parse_path("README"))
# {'filename': 'README', 'name': 'README', 'ext': ''}
log = """
[INFO] Service started
[WARN] High memory usage
[ERROR] Connection timeout
[INFO] Retry attempt 1
[ERROR] Disk full
"""
last_error = log.rfind("[ERROR]")
if last_error != -1:
print(log[last_error:last_error+50]) # [ERROR] Disk full
url = "https://example.com/api?user=123&action=view&token=abc"
last_amp = url.rfind("&")
if last_amp != -1:
last_param = url[last_amp+1:]
print(last_param) # token=abc
def rsplit_once(s, sep):
idx = s.rfind(sep)
if idx == -1:
return [s]
return [s[:idx], s[idx+len(sep):]]
print(rsplit_once("a:b:c:d", ":")) # ['a:b:c', 'd']
import re
def rfind_regex(pattern, string, start=0, end=None):
"""正則版 rfind,回傳最後匹配的 (start, end) 索引元組"""
if end is None:
end = len(string)
matches = list(re.finditer(pattern, string[start:end]))
if not matches:
return -1
last = matches[-1]
return (last.start() + start, last.end() + start)
s = "error_123_warn_456_error_789"
print(rfind_regex(r"error_\d+", s)) # (20, 28) 最後一個 error_789
rfind() 是右向搜尋的標準方法,**回傳索引仍從左計算(0 起始)**,找不到回傳 -1 不拋出例外。搭配 find()、rindex()、index() 組成完整搜尋工具箱。核心應用:路徑解析、日誌分析、URL 處理、最後分隔符定位。理解 start/end 切片語意(含負索引),能精確控制搜尋範圍。