Chcę zapętlić zawartość pliku tekstowego, wyszukać i zamienić w niektórych wierszach i zapisać wynik z powrotem do pliku. Mogłem najpierw załadować cały plik do pamięci, a następnie zapisać go z powrotem, ale prawdopodobnie nie jest to najlepszy sposób na zrobienie tego.
Jak najlepiej to zrobić w ramach następującego kodu?
f = open(file)
for line in f:
if line.contains('foo'):
newline = line.replace('foo', 'bar')
# how to write this newline back to the file
file
cienie predefiniowanej klasy o tej samej nazwie.mkstemp()
zwraca 2-krotkę i(fh, abs_path) = fh, abs_path
nie wiedziałem o tym, kiedy zadałem pytanie.Najkrótszym sposobem byłoby prawdopodobnie użycie modułu fileinput . Na przykład poniższe dodaje w miejscu numery wierszy:
To, co się tutaj dzieje, to:
print
instrukcje zapisują się z powrotem w oryginalnym plikufileinput
ma więcej dzwonków i gwizdków. Na przykład, można go użyć do automatycznego działania na wszystkich plikach wewnątrzsys.args[1:]
, bez konieczności jawnej iteracji nad nimi. Począwszy od Python 3.2, zapewnia on także wygodny menedżer kontekstu do użycia wwith
instrukcji.Podczas
fileinput
świetnie nadaje się do skryptów typu „wyrzucaj”, nie chciałbym używać go w prawdziwym kodzie, ponieważ, co prawda, nie jest on zbyt czytelny ani znajomy. W prawdziwym (produkcyjnym) kodzie warto wydać jeszcze kilka wierszy kodu, aby proces był jawny, a przez to czytelny.Istnieją dwie opcje:
źródło
print(line, end='')
Oto kolejny przykład, który został przetestowany i będzie pasował do wzorców wyszukiwania i zamiany:
Przykładowe zastosowanie:
źródło
searchExp in line
nieline.replace
są operacjami wyrażeń regularnych. Z pewnością użycie przykładu jest nieprawidłowe.if searchExp in line: line = line.replace(searchExp, replaceExpr)
możesz po prostu pisaćline = line.replace(searchExp, replaceExpr)
. Nie jest generowany żaden wyjątek, linia pozostaje niezmieniona.sys.stdout.write(line)
. Dzięki jeszcze raz!To powinno działać: (edycja w miejscu)
źródło
files
powinien to być ciąg znaków zawierający nazwę pliku, a nie obiekt pliku .Na podstawie odpowiedzi Thomasa Watnedala. Nie odpowiada to jednak dokładnie na pytanie liniowe w pierwotnym pytaniu. Funkcja może nadal zastępować liniowo
Ta implementacja zastępuje zawartość pliku bez użycia plików tymczasowych, w wyniku czego uprawnienia do plików pozostają niezmienione.
Również re.sub zamiast replace pozwala na zamianę wyrażeń regularnych zamiast zamiany zwykłego tekstu.
Odczytywanie pliku jako pojedynczego ciągu zamiast wiersza po wierszu pozwala na dopasowanie wielu wierszy i zamianę.
źródło
rb
iwb
atrybutów podczas otwierania plików, ponieważ pozwoli to zachować oryginalne zakończenia liniiJak sugeruje lassevk, zapisz nowy plik na bieżąco, oto przykładowy kod:
źródło
Jeśli potrzebujesz ogólnej funkcji, która zastępuje dowolny tekst innym tekstem, jest to prawdopodobnie najlepsza droga, szczególnie jeśli jesteś fanem wyrażeń regularnych:
źródło
Bardziej pythonowym sposobem byłoby użycie menedżerów kontekstu, takich jak poniższy kod:
Pełny fragment kodu można znaleźć tutaj .
źródło
Utwórz nowy plik, skopiuj linie ze starego do nowego i wykonaj zamianę przed zapisaniem linii do nowego pliku.
źródło
Rozwijając odpowiedź @ Kirana, którą zgadzam się, jest bardziej zwięzła i Pythonic, dodaje to kodeki do obsługi odczytu i zapisu UTF-8:
źródło
Wykorzystując odpowiedź hamishmcn jako szablon, byłem w stanie wyszukać wiersz w pliku, który pasuje do mojego wyrażenia regularnego i zastąpić go pustym ciągiem.
źródło
fileinput
jest dość proste, jak wspomniano w poprzednich odpowiedziach:Wyjaśnienie:
fileinput
mogę zaakceptować wiele plików, ale wolę zamknąć każdy pojedynczy plik, gdy tylko zostanie przetworzony. Tak umieszczony singielfile_path
wwith
instrukcji.print
instrukcja nie drukuje niczego, gdyinplace=True
, ponieważSTDOUT
jest przekazywana do oryginalnego pliku.end=''
wprint
instrukcji jest wyeliminowanie pośrednich pustych nowych wierszy.Może być używany w następujący sposób:
źródło
jeśli usuniesz wcięcie w podobny sposób poniżej, przeszuka ono i zastąpi wiele wierszy. Zobacz na przykład poniżej.
źródło