HOWTO · Python
Python 在文件中查找字符串
本教程演示了如何在 Python 中搜索文本文件中的字符串。
本页内容
要在文本文件中查找字面子字符串,可以使用 read() 和 in 获取布尔结果;需要查看匹配行时使用 readlines();需要字符位置时使用 find()。对于大型文件或面向字节的数据,mmap 可以在文件映射上搜索。以下示例使用相同的小段文本,便于比较各自的结果和取舍。每个示例都可以运行;文中展示的输出与所提供的执行记录一致。
使用 read() 和 in 搜索文件内容
read() 方法会将文件剩余内容作为一个字符串返回。使用 Python 的 in 运算符,可以检查该字符串是否包含要查找的字面文本。表达式会得到 True 或 False,适合只需判断子字符串是否出现的情况。
这种方法直接明了,但会先将整个文件读入内存再进行搜索。它适合较小或中等大小的文本文件,也适用于还需要完整文件内容的情况。如果文件太大,无法舒适地放入内存,可以改用逐行处理或文件映射的方式。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "notes.txt"
path.write_text("status=ready\nowner=Sam\n", encoding="utf-8")
with path.open(encoding="utf-8") as file:
found = "ready" in file.read()
print(found)
True
使用 readlines() 逐行搜索
readlines() 方法会返回一个列表,其中包含文件的各行;如果行末有换行符,换行符也会包含在内。你可以用 in 检查每一行,并在首次匹配时停止。这种方式适合需要处理匹配行本身的场景,例如决定要显示或处理哪条记录。
虽然循环可以提前停止,readlines() 已经把所有行都读入列表。因此,内存用量会随文件大小增长。对于需要逐步处理的大型文件,可以直接用 for line in file 遍历打开的文件;这样无需先构建完整列表,同时仍可逐行执行相同的匹配逻辑。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "notes.txt"
path.write_text("status=ready\nowner=Sam\n", encoding="utf-8")
with path.open(encoding="utf-8") as file:
for line in file.readlines():
if "owner" in line:
print(line.rstrip())
break
owner=Sam
使用 find() 获取匹配位置
如果你需要知道首次匹配的字符索引,而不只是判断是否匹配,可以对 read() 返回的内容调用字符串的 find() 方法。索引从零开始:匹配项位于开头时返回 0,位于后面时则返回它在字符串中的位置。找不到匹配项时,find() 会返回 -1。请显式检查这个值,不要把所有结果都当作布尔值,因为在 Python 中 0 会被视为假值。
返回的位置是已解码 Python 字符串中的字符数,不是文件中的字节数。如果文件含有非 ASCII 文本,请使用合适的编码打开文本。若需要字节偏移量或内容是二进制数据,可以使用 mmap 和 bytes 模式进行面向字节的搜索。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "notes.txt"
path.write_text("status=ready\nowner=Sam\n", encoding="utf-8")
with path.open(encoding="utf-8") as file:
contents = file.read()
position = contents.find("ready")
print(position)
print(contents.find("missing"))
7
-1
使用 mmap 搜索大型文件
mmap 模块会将文件映射为支持搜索的类字节对象,无需先创建一个包含整个文件内容的 Python 字符串。处理大型文件时,这种方式可能有用,但不能保证搜索速度更快:性能取决于文件、存储设备、操作系统和访问模式。映射也会占用操作系统资源,因此用完后应将其关闭。
使用 bytes 模式(例如 b"ready")搜索映射。与文本示例不同,这种搜索检查的是编码后的字节,并返回字节偏移量。模式必须是 bytes;普通字符串(例如 "ready")是另一种类型。此示例在二进制模式下打开文件,并使用与相同 ASCII 文本对应的 UTF-8 字节。
运行以下示例:
本节中的代码以及显示的标签或输出仍为英文。
import mmap
from pathlib import Path
from tempfile import TemporaryDirectory
with TemporaryDirectory() as directory:
path = Path(directory) / "notes.txt"
path.write_bytes(b"status=ready\nowner=Sam\n")
with path.open("rb") as file:
with mmap.mmap(file.fileno(), 0, access=mmap.ACCESS_READ) as mapped:
print(mapped.find(b"ready"))
7
选择合适的方法
如果只需要布尔结果,而且完整文本可以轻松放入内存,就使用 read() 和 in。如果需要获取行列表并查看或保留这些行,可以使用 readlines();请记住,列表会保存整个文件。对于可以逐行独立处理的大型文本文件,直接遍历文件对象,不要把所有行都存进列表。
如果需要首次字面匹配的字符位置,就使用 find()。用 -1 判断未找到,并将 0 视为有效位置。如果适合进行文件映射的字节搜索,而且需要字节偏移量,就使用 mmap;请将目标编码为 bytes,也不要假设映射总会更快。这些方法搜索的是字面文本。如果任务需要匹配模式、忽略大小写或找出每次出现的位置,请选择专门满足这些需求的方法。