Dies kann ziemlich effizient erfolgen:
- Finding alle
- Spiele über newlines Looping, Speichern des
{offset: line_number}
mappin g bis zum letzten Spiel.
- Suchen Sie für jedes Spiel rückwärts den Offset des ersten Zeilenvorschubs und suchen Sie nach der Zeilennummer in der Karte.
Dies vermeidet das Zurückzählen für jede Übereinstimmung bis zum Anfang der Datei.
Die folgende Funktion ist ähnlich re.finditer
def finditer_with_line_numbers(pattern, string, flags=0):
'''
A version of 're.finditer' that returns '(match, line_number)' pairs.
'''
import re
matches = list(re.finditer(pattern, string, flags))
if not matches:
return []
end = matches[-1].start()
# -1 so a failed 'rfind' maps to the first line.
newline_table = {-1: 0}
for i, m in enumerate(re.finditer(r'\n', string), 1):
# don't find newlines past our last match
offset = m.start()
if offset > end:
break
newline_table[offset] = i
# Failing to find the newline is OK, -1 maps to 0.
for m in matches:
newline_offset = string.rfind('\n', 0, m.start())
line_number = newline_table[newline_offset]
yield (m, line_number)
Wenn Sie den Inhalt möchten, können Sie die letzte Schleife mit ersetzen:
for m in matches:
newline_offset = string.rfind('\n', 0, m.start())
newline_end = string.find('\n', m.end()) # '-1' gracefully uses the end.
line = string[newline_offset + 1:newline_end]
line_number = newline_table[newline_offset]
yield (m, line_number, line)
Beachten Sie, dass es schön wäre, um zu vermeiden, zu schaffen eine Liste von finditer
, aber das bedeutet, dass wir nicht wissen, wann die Speicherung von Zeilenumbrüchen (wo es am Ende viele neue Zeilen speichern könnte, auch wenn das einzige Muster Übereinstimmung am Anfang der Datei ist).
Wenn es wichtig war, alle Übereinstimmungen zu vermeiden, ist es möglich, einen Iterator zu erstellen, der Zeilenumbrüche nach Bedarf scannt, obwohl dies nicht sicher ist, dass Sie in der Praxis viel davon profitieren würden.
Suchen Sie nach tatsächlichen Zeilennummern oder nach den Zahlen, die Sie nach dem '####' geschrieben haben? – interjay
danke, ich brauche die tatsächlichen Zeilennummern, die Probe ist irreführend, ich aktualisierte es. –