można to zrobić dość skutecznie przez:
- Znalezienie wszystkie mecze
- zapętlenie nad nowymi liniami, przechowywania
{offset: line_number}
Mappin g aż do ostatniego meczu.
- Dla każdego meczu, znajdź wcześniej odsunięcie pierwszego nowego wiersza i wyszukaj jego numer linii na mapie.
Pozwala to uniknąć liczenia z powrotem do początku pliku dla każdego meczu.
Poniższa funkcja jest podobna do 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)
Jeśli chcesz zawartość można zastąpić ostatnią pętlę z:
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)
Zauważ, że byłoby miło, aby uniknąć konieczności tworzenia lista od finditer
, ale oznacza to, że nie będziemy wiedzieć, kiedy przestać zapisywać nowe linie (gdzie może to skończyć przechowywanie wielu linii, nawet jeśli jedyne dopasowanie wzorca znajduje się na początku pliku).
Jeśli ważne jest, aby unikać przechowywania wszystkich meczów - możliwe jest wykonanie iteratora, który skanuje znaki nowej linii zgodnie z potrzebą, choć nie jest pewne, czy w praktyce przyniesie to wiele korzyści.
Czy szukasz aktualnych numerów linii lub numerów, które napisałeś po "####"? – interjay
dziękuję, potrzebuję rzeczywistych numerów linii, próbka wprowadza w błąd, zaktualizowałem ją. –