Python实现文本文件多行字符串匹配并返回起始行号
How to Find Multi-Line Matches and Get the Starting Line Number
Great question—your two initial approaches each hit a clear limitation: reading the whole file into a string loses line number context, while checking line-by-line can’t handle cross-line matches. Let’s fix this with two practical solutions tailored to your needs:
Option 1: Improve the Regex Approach (Track Line Numbers)
We can keep using regex, but first capture the positions of every newline to map match indices back to line numbers. This works even if your pattern spans more than two lines:
import re file_path = "example.txt" with open(file_path, "r") as f: content = f.read() # Record the start position of every line (including the first line at index 0) line_starts = [0] + [match.end() for match in re.finditer("\n", content)] # Define your multi-line pattern (use re.DOTALL if you need . to match newlines) pattern = re.compile(r"second line\nThis third line") for match in pattern.finditer(content): start_idx = match.start() # Find the first line start position that comes after the match's start # Adjust +1/-1 if you count lines from 0 instead of 1 line_number = next(i for i, pos in enumerate(line_starts) if pos > start_idx) print(f"Match found starting on line: {line_number}")
Option 2: Line-by-Line with Previous Line Caching (Simpler for Two-Line Matches)
If you only need to match exactly two lines, this method is more efficient and straightforward. We’ll track the previous line and check if its combination with the current line matches your target:
target = "second line\nThis third line" # Split the target into its two component lines target_first, target_second = target.split("\n") with open("example.txt", "r") as f: prev_line = "" # Use start=1 to count lines from 1; remove it to start at 0 for line_no, current_line in enumerate(f, start=1): # Strip trailing newlines if your target doesn't include them, or omit rstrip() to match exactly if prev_line.rstrip("\n") == target_first and current_line.rstrip("\n") == target_second: print(f"Match found starting on line: {line_no - 1}") break prev_line = current_line else: print("String not found")
Quick Notes:
- Adjust the
enumeratestartparameter if you want line numbers to start at 0 instead of 1. - If your pattern uses variable whitespace (like multiple newlines or spaces), tweak the regex or line comparison to account for that (e.g., use
re.VERBOSEorstrip()for flexible matching).
内容的提问来源于stack exchange,提问作者Nic
相关产品推荐
相关产品推荐

