Program zamieniający jedno słowo w pliku na drugie

Odpowiedz Nowy wątek
2018-11-18 22:36
0

Zwracam się z prośbą o to czy wiecie może jak napisać program, który zmieniałby jakieś jedno wybrane słowo. Mianowicie mam plik tekstowy ze słowem UNK i chciałbym je zamienić na DGD (,np. mam 1UNK chce zamienić na 1DGD). W jaki sposób mogę to zrobić? Znalazłem, że może to zrobić funkcja replace, więc zrobiłem to tak.

membrane_box = ''
membrane_box2 = ''
f1 = open('membrane_box', 'r')
f2 = open('membrane_box2', 'w')
pattern=f1.readline()
while pattern != '':
    if pattern == "UNK":
        str.replace("UNK", "DGD")
f1.close()
f2.close()

Ale skrypt ruszył i się nie kończy chyba jak go w linuxie w terminalu wpisałem

Pozostało 580 znaków

2018-11-18 23:29
1
with open('torepl.txt', 'r') as myfile:
    data=myfile.read().replace('\n', '')
    print(data)
    data = data.replace("UNK", "DGD")
    print(data)

Teraz string data Możesz zapisać gdziekolwiek.


Przy wielkich plikach (nawet kilkaset mb, nie mówiąc o gb), polecam mimo wszystko lecieć z jakimś buforem, nawet o zmiennej długości jak readline. Inaczej skrypt będzie się wykonywał baardzo długo. Poza tym, z ciekawości, czemu usuwasz znaki końca wiersza? - Guaz 2018-11-20 01:27
Interpreter tego jakoś nie zoptymalizuje? - lion137 2018-11-20 09:55
Nie wydaje mi się, skoro rozkazujesz mu poprzez read wczytać wszystko do zmiennej jako ogromny string :). Jeśli pracujesz na ubuntu lub czymś tego rodzaju, wygeneruj sobie plik 1 GB, i zobacz po instrukcji read jak dużo będzie ci zajmował pamięci :). Wskaźnik to jedno, a cała zawartość pliku w zmiennej, to drugie :). - Guaz 2018-11-20 11:37
Hehe, "interpreter Pythona" oraz "zoptymalizuje" w jedynym zdaniu. W przypadku CPythona (czyli domyślnej implementacji) to się po prostu nie dzieje (i nie ma jak, program po dość naiwnej kompilacji do bytecodu nie ma narzędzi by przeprowadzić potrzebną analizę). - enedil 2018-11-21 03:04

Pozostało 580 znaków

2018-11-19 06:36
1

Jeśli chcesz wiedzieć co z Twoim kodem jest nie tak...

2 pierwsze linie.. deklarujesz dwie zmienne membrane_box i membrane_box2 przypisujesz im pusty tekst i nic więcej już z nimi nie robisz, więc są niepotrzebne.

readline() odczytuje tylko pojedynczą linię tekstu, jeżeli będą w pliku dwie lub więcej to resztę pominie.

pętla while się nie kończy bo pattern zawsze zawiera tą jedną jedyną odczytaną linie tekstu nic więcej, bo nic innego do niej później nie przypisujesz, więc zawsze jest różne ''

if pattern == "UNK" - ten warunek jest spełniony jedynie wtedy gdy w pliku masz "UNK" i nic innego, jak masz np. "1UNK" to już nie zadziała.

str.replace("UNK", "DGD") - tego się tak nie używa. Chcesz zamienić fragment tekstu w zmiennej pattern, więc jakoś musisz to zasygnalizować, a w tej linii kodu o tym nawet nie wspominasz ;)
powinno być pattern = pattern.replace("UNK", "DGD")
i tu działa magia bo... nie musisz używać if'a, replace sam sprawdzi czy jest tam UNK i jeżeli jest to zamieni na DGD, a jeżeli nie to nic nie zmieni, a także nie musisz używać pętli gdyż replace domyślnie zamienia każde wystąpienie.

Heh, gdyby ten str.replace się kiedykolwiek wykonał, to OP by dostał błąd złej liczby argumentów. - enedil 2018-11-19 08:09

Pozostało 580 znaków

2018-11-20 01:33

Jeśli plik jest bardzo duży, np. jakiś zrzut z logów albo inne cholerstwo o długości nie przerabialnej dla przeciętnego człowieka który się nudzi przy trzeciej linijce, polecam ten sposób:

with open('membrane_box', 'r') as f1:
  with open('membrane_box2', 'w') as f2:
    line =  f1.readline()
    while line:
      f2.write(line.replace("UNK", "DGD")+"\n")
      line = f1.readline()

Przy klauzuli with, plik zamknie ci się automatycznie gdy zagnieżdżenie kodu wróci do początku, albo zakończy się program.

@Edit: Alternatywnie tak, ale nie jestem pewien czy to w pythonie tak było że readlines nie wczytuje wszystkiego tylko tworzy generator.

with open('membrane_box', 'r') as f1:
  with open('membrane_box2', 'w') as f2:
    for line in f1.readlines():
      f2.write(line.replace("UNK", "DGD"))

@Edit2:
Jak przypomniał @AsterFV w komentarzu, lepiej iterować przez plik w ten sposób aby działało to jak generator :)

with open('membrane_box', 'r') as f1:
  with open('membrane_box2', 'w') as f2:
    for line in f1:
      f2.write(line.replace("UNK", "DGD"))

Linux Mint
Arduino / Python 3.5.2
edytowany 4x, ostatnio: Guaz, 2018-11-23 13:21
readlines() wczyta wszystko ale możesz zrobić for line in f1: żeby iterować plik f1 jak generator. - AsterFV 2018-11-23 11:05
No właśnie nie pamiętałem czy bezpośrednio in f1 tworzy generator czy in z readlines(). Dzięki za przypomnienie :) - Guaz 2018-11-23 13:20
Wielkie dzięki działa super, a ten pierwszy program, dlaczego pętla while się zamyka, dlaczego pętla while nie idzie w nieskończoność? Skąd wiadomo kiedy jest zakończenie pętli while, bo nie rozumiem? - Morgotheron 2018-12-05 19:18
Ponieważ nie zmieniasz zmiennej pattern wewnątrz while (czyli po wcięciu). Wystarczyłoby abyś dodał po while pattern != '': to samo co przed while, czyli: pattern=f1.readline(). I już by się kręciło. sprawdź sobie kod: i=0 <enter> while i == 100: <enter> print("coś robię") na stronie pythontutor.com | Tam masz fajnie przedstawione graficznie, dopóki nie dodasz wewnątrz while i+=1 pętla będzie biec w nieskończoność. - Guaz 2018-12-05 19:23
W sensie chodziło mi w twoim kodzie while line: f2.write(line.replace("UNK", "DGD")+"\n") line = f1.readline() dlaczego program nie odczytuje kolejnych pustych linii, aż w nieskończoność tylko ładnie się zakańcza - Morgotheron 2018-12-05 19:25
Aaa... Dlatego że sprawdza czy linia istnieje. Pusta linia zawiera dokładnie: "\n" które jest ignorowane przez readline(), zaś zakończenie pliku to szczególny znacznik. Najprościej sobie to sprawdzić w ten sposób: print(f1.readlines()) koniecznie z 's' na końcu wskazującym na liczbę mnogą. Zobaczysz że puste linie w liście będą wyświetlane jak powyżej podałem w przykładzie :). Zaś kończącej plik nie będzie, bo tzw. EOF (End Of File) nie jest odczytywany :D . Nie bez powodu we write na końcu jest przejście do nowej linii poprzez +"\n" :) - Guaz 2018-12-05 19:41

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0