Python基礎指南之字符串查找與替換的常用方法詳解
一、開篇:字符串方法的魅力
今天開始,我們要進入字符串方法的世界——那些幫你在字符串中查找內(nèi)容、替換內(nèi)容、判斷內(nèi)容的強大工具。
Python的字符串有40多個內(nèi)置方法。別被這個數(shù)字嚇到——日常開發(fā)中真正高頻使用的大概15個左右。我將它們分成三組來講:查找與替換(本文)、分割與拼接、大小寫與判斷。
查找和替換是你處理文本時最常用的操作——從一段文字中找關鍵詞、替換模板中的占位符、提取特定格式的數(shù)據(jù),全都離不開它們。
二、find() 和 rfind():查找子串位置
2.1 find() 基本用法
find() 在字符串中查找子串,返回第一次出現(xiàn)的位置索引。如果找不到,返回 -1(而不是報錯)。
text = 'Python is easy, Python is powerful'
# 查找子串
print(text.find('Python')) # 0(第一次出現(xiàn)的位置)
print(text.find('is')) # 7
print(text.find('Java')) # -1(沒找到)
# 指定查找范圍:find(sub, start, end)
print(text.find('Python', 10)) # 17(從索引10開始找)
print(text.find('Python', 0, 10)) # -1(在0到10范圍內(nèi)沒找到)
2.2 rfind():從右邊開始查找
text = 'Python is easy, Python is powerful'
# rfind:找最后一次出現(xiàn)的位置
print(text.rfind('Python')) # 17
print(text.rfind('is')) # 22(第二個'is')
print(text.find('is')) # 7(第一個'is')
2.3 find() 實戰(zhàn)應用
# 提取文件擴展名
def get_file_extension(filename):
dot_index = filename.rfind('.')
if dot_index == -1:
return '' # 沒有擴展名
return filename[dot_index:]
print(get_file_extension('report.pdf')) # .pdf
print(get_file_extension('archive.tar.gz')) # .gz
print(get_file_extension('README')) # ''
# 提取URL中的協(xié)議
def get_url_protocol(url):
separator = url.find('://')
if separator == -1:
return 'unknown'
return url[:separator]
print(get_url_protocol('https://example.com')) # https
print(get_url_protocol('ftp://files.server')) # ftp
# 查找所有出現(xiàn)的位置
def find_all_occurrences(text, substring):
"""查找子串在文本中出現(xiàn)的所有位置"""
positions = []
start = 0
while True:
pos = text.find(substring, start)
if pos == -1:
break
positions.append(pos)
start = pos + 1
return positions
text = 'abababab'
print(find_all_occurrences(text, 'ab')) # [0, 2, 4, 6]
三、index() 和 rindex():查找但報錯
和 find() 幾乎一樣,唯一的區(qū)別是:找不到時拋出 ValueError 而不是返回 -1。
text = 'Python編程'
# 找到了——行為完全一樣
print(text.index('Python')) # 0
print(text.index('編程')) # 6
# 區(qū)別:找不到時報錯
# print(text.index('Java')) # ValueError: substring not found
# 安全的用法——用try-except包裹
def safe_index(text, substring):
try:
return text.index(substring)
except ValueError:
return -1
print(safe_index('Python', 'Java')) # -1
選擇 find() 還是 index() ?
- 大多數(shù)情況用
find():更安全,返回-1即可判斷 - 當子串必須存在時用
index():找不到說明數(shù)據(jù)有問題,報錯比靜默失敗更好
四、count():統(tǒng)計出現(xiàn)次數(shù)
text = 'banana'
print(text.count('a')) # 3
print(text.count('na')) # 2
print(text.count('z')) # 0
# 指定范圍統(tǒng)計
print(text.count('a', 3)) # 2(從索引3開始統(tǒng)計)
print(text.count('a', 0, 3)) # 1(在0到3范圍內(nèi)統(tǒng)計)
# 實際應用
def count_keywords(text, keywords):
"""統(tǒng)計文本中各個關鍵詞出現(xiàn)的次數(shù)"""
result = {}
for keyword in keywords:
result[keyword] = text.lower().count(keyword.lower())
return result
article = """
Python是一種解釋型語言。Python的設計哲學強調(diào)代碼的可讀性。
Python支持多種編程范式,包括面向?qū)ο蠛秃瘮?shù)式編程。
"""
word_counts = count_keywords(article, ['Python', '編程', '語言'])
print(word_counts)
# {'Python': 3, '編程': 2, '語言': 1}
五、startswith() 和 endswith():首尾判斷
5.1 基本用法
filename = 'report_2024.pdf'
print(filename.startswith('report')) # True
print(filename.endswith('.pdf')) # True
print(filename.endswith('.txt')) # False
# 可以傳入元組來匹配多個選項
print(filename.endswith(('.pdf', '.doc', '.docx'))) # True
print(filename.endswith(('.jpg', '.png', '.gif'))) # False
5.2 指定查找范圍
text = 'Python Programming'
# startswith可以帶start和end參數(shù)
print(text.startswith('Pro', 7)) # True(從索引7開始看)
print(text.startswith('Pro', 7, 10)) # True
# endswith也有范圍參數(shù)(檢查指定范圍內(nèi)的結尾)
print(text.endswith('ing', 0, 17)) # True(檢查text[0:17]的結尾)
5.3 實戰(zhàn)應用
# 過濾文件列表
def filter_files_by_extension(files, extensions):
"""過濾出指定擴展名的文件"""
return [f for f in files if f.lower().endswith(extensions)]
files = ['data.csv', 'report.pdf', 'photo.jpg', 'script.py', 'notes.txt']
csv_and_py = filter_files_by_extension(files, ('.csv', '.py'))
print(csv_and_py) # ['data.csv', 'script.py']
# 按前綴分類
def categorize_by_prefix(items, prefix_map):
"""根據(jù)前綴對項目分類"""
categories = {key: [] for key in prefix_map}
categories['other'] = []
for item in items:
categorized = False
for prefix, category in prefix_map.items():
if item.startswith(prefix):
categories[category].append(item)
categorized = True
break
if not categorized:
categories['other'].append(item)
return categories
files = ['img_001.jpg', 'doc_report.pdf', 'img_002.png', 'doc_notes.txt']
prefix_map = {'img_': 'images', 'doc_': 'documents'}
print(categorize_by_prefix(files, prefix_map))
# {'images': ['img_001.jpg', 'img_002.png'],
# 'documents': ['doc_report.pdf', 'doc_notes.txt'],
# 'other': []}
六、replace():替換內(nèi)容
6.1 基本用法
text = 'Hello, World! World is beautiful.'
# 基本替換
print(text.replace('World', 'Python'))
# Hello, Python! Python is beautiful.
# 限制替換次數(shù)
print(text.replace('World', 'Python', 1))
# Hello, Python! World is beautiful.(只替換第一個)
# 刪除內(nèi)容(替換為空字符串)
print(text.replace('World', ''))
# Hello, ! is beautiful.
# (注意:多了空格,可能需要額外處理)
# 替換不存在的子串——靜默返回原字符串
print(text.replace('Java', 'Python')) # 原樣返回
6.2 replace() 的高級應用
# 清理文本中的多余空白
def clean_whitespace(text):
"""將連續(xù)的空白字符替換為單個空格"""
import re
# replace處理簡單場景
text = text.replace('\t', ' ').replace('\n', ' ')
# 連續(xù)的多個空格替換為單個空格
while ' ' in text:
text = text.replace(' ', ' ')
return text.strip()
raw_text = 'Hello world\t\tPython \n\n 編程'
print(clean_whitespace(raw_text)) # Hello world Python 編程
# 模板替換
def fill_template(template, **kwargs):
"""用字典的值填充模板中的占位符"""
result = template
for key, value in kwargs.items():
placeholder = '{' + key + '}'
result = result.replace(placeholder, str(value))
return result
template = '尊敬的{name},您的訂單{order_id}已{status}。'
message = fill_template(
template,
name='小明',
order_id='20240530001',
status='發(fā)貨'
)
print(message) # 尊敬的小明,您的訂單20240530001已發(fā)貨。
# replace的鏈式調(diào)用
text = 'a b c d e'
result = text.replace('a', '1').replace('b', '2').replace('c', '3')
print(result) # 1 2 3 d e
# 多組替換——使用字典
def multi_replace(text, replacements):
"""一次性執(zhí)行多組替換"""
for old, new in replacements.items():
text = text.replace(old, new)
return text
replace_map = {
'&': '&',
'<': '<',
'>': '>',
'"': '"',
"'": '''
}
html_text = '<div class="content">Hello & Welcome</div>'
escaped = multi_replace(html_text, replace_map)
print(escaped)
七、translate() 和 maketrans():批量字符映射
對于單字符的批量替換,translate() 比多次調(diào)用 replace() 高效得多:
# 創(chuàng)建字符映射表
# str.maketrans(x, y, z)
# x: 要被替換的字符
# y: 替換成的字符(與x逐一對應)
# z: 要刪除的字符(可選)
# 凱撒密碼——每個字母后移3位
import string
lowercase = string.ascii_lowercase # 'abcdefghijklmnopqrstuvwxyz'
shifted = lowercase[3:] + lowercase[:3] # 'defghijklmnopqrstuvwxyzabc'
translation_table = str.maketrans(lowercase + lowercase.upper(),
shifted + shifted.upper())
message = 'Hello, Python!'
encrypted = message.translate(translation_table)
print(encrypted) # Khoor, Sbwkrq!
# 刪除所有數(shù)字和標點符號
text = '你好,Python3!這是一個測試2024。'
# 方法1:刪除特定字符
digits_and_punctuation = '0123456789,。?。?、:;""''()'
translator = str.maketrans('', '', digits_and_punctuation)
cleaned = text.translate(translator)
print(cleaned) # 你好Python這是一個測試
# 使用translate做簡單的文本消毒
def sanitize_filename(filename):
"""清理文件名中的非法字符"""
illegal_chars = r'<>:"/\|?*'
translator = str.maketrans(illegal_chars, '_' * len(illegal_chars))
return filename.translate(translator)
print(sanitize_filename('report:2024/05/30.pdf'))
# report_2024_05_30.pdf
什么時候用 translate() 而不是 replace()?
- 單字符→單字符的批量映射:
translate()快得多 - 多字符子串→多字符子串:只能用
replace()
八、strip()系列:去除首尾字符
8.1 strip() / lstrip() / rstrip()
# strip():去除首尾的空白字符(默認)
text = ' Hello, World! \n'
print(repr(text.strip())) # 'Hello, World!'
# 去除指定的字符(不是子串,是字符集合?。?
text = '###Hello, World!###'
print(text.strip('#')) # 'Hello, World!'
text = 'www.example.com'
print(text.strip('w.moc')) # 'example'
# 注意:strip('w.moc')是一直去除首尾出現(xiàn)的w、.、m、o、c這些字符
# 直到首尾不再出現(xiàn)這些字符為止
# lstrip():只去除左側
text = ' Hello '
print(repr(text.lstrip())) # 'Hello '
# rstrip():只去除右側
text = ' Hello '
print(repr(text.rstrip())) # ' Hello'
8.2 strip() 實戰(zhàn)案例
# 清理用戶輸入
def clean_user_input(text):
"""清理用戶輸入的首尾空白和特殊符號"""
return text.strip().strip('.,;:!?。,;:!?')
inputs = [' 小明 ', '小紅。。。', ' 小剛,,, ', ',小麗。']
for inp in inputs:
print(repr(clean_user_input(inp)))
# '小明'
# '小紅'
# '小剛'
# '小麗'
# 讀取配置文件中的值,去除注釋和空白
def parse_config_line(line):
"""解析配置文件的一行"""
# 去除注釋(#后面的內(nèi)容)
comment_index = line.find('#')
if comment_index != -1:
line = line[:comment_index]
# 去除首尾空白
return line.strip()
config_lines = [
'server = localhost # 數(shù)據(jù)庫服務器地址',
'port = 3306 # 數(shù)據(jù)庫端口',
'username = admin',
''
]
for line in config_lines:
result = parse_config_line(line)
if result:
print(f'解析:{result}')
九、replace() vs re.sub():何時用正則
replace() 只能替換確定的字符串。如果需要模式匹配(如"所有數(shù)字"、“郵箱地址”),就需要正則表達式:
import re
text = '我的電話是138-1234-5678,他的電話是139-8765-4321。'
# replace做不到——每次號碼都不一樣
# 用正則表達式
masked = re.sub(r'\d{3}-\d{4}-\d{4}', '***-****-****', text)
print(masked) # 我的電話是***-****-****,他的電話是***-****-****。
# replace能做到——不需要正則
text = 'Hello, WORLD! Hello, world!'
print(text.replace('Hello', 'Hi')) # Hi, WORLD! Hi, world!
# replace做不到——大小寫不敏感的替換
print(re.sub('hello', 'Hi', text, flags=re.IGNORECASE)) # Hi, WORLD! Hi, world!
原則:能用 replace() 解決的就用 replace(),簡單清晰;需要模式匹配時才用正則。
十、查找與替換的性能對比
import time
text = 'a' * 10000 + 'target' + 'a' * 10000
# find 比 in 更靈活(可以指定位置)
start = time.perf_counter()
pos = text.find('target')
elapsed = time.perf_counter() - start
print(f'find: {elapsed:.8f}秒, 位置={pos}')
# count 和 find 性能差不多
start = time.perf_counter()
cnt = text.count('a')
elapsed = time.perf_counter() - start
print(f'count: {elapsed:.8f}秒, 數(shù)量={cnt}')
# replace vs translate(字符替換場景)
chars_to_replace = 'abcdefghijklmnopqrstuvwxyz'
chars_replacement = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
# replace方式
start = time.perf_counter()
result1 = text
for old, new in zip(chars_to_replace, chars_replacement):
result1 = result1.replace(old, new)
elapsed_replace = time.perf_counter() - start
print(f'replace: {elapsed_replace:.4f}秒')
# translate方式
start = time.perf_counter()
table = str.maketrans(chars_to_replace, chars_replacement)
result2 = text.translate(table)
elapsed_translate = time.perf_counter() - start
print(f'translate: {elapsed_translate:.4f}秒')
# translate快很多倍!
十一、本篇小結
字符串查找與替換方法速查:
| 方法 | 功能 | 找不到時 |
|---|---|---|
find() | 查找子串位置 | 返回-1 |
rfind() | 從右查找 | 返回-1 |
index() | 查找子串位置 | 報ValueError |
rindex() | 從右查找 | 報ValueError |
count() | 統(tǒng)計出現(xiàn)次數(shù) | 返回0 |
startswith() | 判斷開頭 | 返回False |
endswith() | 判斷結尾 | 返回False |
replace() | 替換子串 | 返回原字符串 |
translate() | 批量字符映射 | N/A |
strip() | 去除首尾字符 | 可能返回空串 |
這些方法構成了Python字符串處理的基礎。日常開發(fā)中,find() + replace() + strip() + startswith()/endswith() 這幾個占了我90%的字符串查找替換操作。下一篇我們學習分割與拼接——處理CSV、日志、路徑等結構化文本的核心技能。
以上就是Python基礎指南之字符串查找與替換的常用方法詳解的詳細內(nèi)容,更多關于Python字符串查找與替換的資料請關注腳本之家其它相關文章!
相關文章
python?rsa和Crypto.PublicKey.RSA?模塊詳解
這篇文章主要介紹了python?rsa和Crypto.PublicKey.RSA?模塊,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-04-04
Python實現(xiàn)刪除Excel表格中重復行的實用方法
在整理客戶名單、導入調(diào)查數(shù)據(jù)或合并多個數(shù)據(jù)源時,Excel?表格中很容易出現(xiàn)重復記錄,本文將介紹?4?種刪除?Excel?重復行的方法,大家可以根據(jù)需要進行選擇2026-03-03
使用Python來開發(fā)Markdown腳本擴展的實例分享
這篇文章主要介紹了使用Python來開發(fā)Markdown腳本擴展的實例分享,文中的示例是用來簡單地轉(zhuǎn)換文檔結構,主要為了體現(xiàn)一個思路,需要的朋友可以參考下2016-03-03
Python實現(xiàn)CSV轉(zhuǎn)TXT格式(單文件+批量處理)
CSV格式因結構簡潔、易與表格軟件兼容而被廣泛使用,但TXT格式具有更強的通用性、更低的存儲冗余,下面我們就來看看如何使用Python實現(xiàn)二者的轉(zhuǎn)換吧2026-01-01
使用pycharm和pylint檢查python代碼規(guī)范操作
這篇文章主要介紹了使用pycharm和pylint檢查python代碼規(guī)范操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-06-06
淺談pandas中DataFrame關于顯示值省略的解決方法
下面小編就為大家分享一篇淺談pandas中DataFrame關于顯示值省略的解決方法,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-04-04

