Inna twórczość > C, C++

[C++] Masowa modyfikacja plików tekstowych

(1/1)

Bogdan Zwei:
Chcę zmodyfikować około 6000 plików na raz, które są też zaszyfrowane odpowiednio, żeby nikt nie miał do nich wglądu. Poszperałem trochę w internecie, tutaj tutorial, który nasunął mnie na odpowiednią bibliotekę https://www.youtube.com/watch?v=h2Taf16gQDI, a tu cała biblioteka do wglądu http://www.cplusplus.com/reference/fstream/fstream/. Mój problem polega na tym, że każdy plik ma jakąś linijkę, która się powtarza, a potrzebuje zmiany, lecz nie wiem jak wyszukać odpowiednie słowo i właśnie o to chciałem zapytać.
Nie mogę zdradzić, co pliki zawierają (nie ja sobie to ubzdurałem :P), więc załóżmy, że każdy plik ma linijkę z tekstem "królik", a odpowiedni program szyfruje go i teraz mamy napis "ąiwg24ć" i tylko program wie, co on oznacza, a chcę zmienić ten napis ("królik") na "drzewo", w każdym pliku, więc potrzebuję jakieś funkcji, która sama wyszuka dane słowo/słowa (w jednym pliku może się powtórzyć to samo słowo) i go zamieni.


Dodatkowo, jeśli jest to możliwe i w miarę nie skomplikowane, potrzebowałbym funkcję, która by przeskakiwała do następnego pliku (i jeśli to konieczne, otwierała kolejny folder) po edycji. Czyli, plik 1 jest edytowany, wskakuje do pliku 2 w tym samym folderze, po czym folder jest pusty, ale jest kolejny folder, który znowu ma 4 pliki i jeden folder, więc otwiera ten kolejny folder, po czym edytuje tam wszystko, otwiera podfoldery i je edytuje, przeskakuje do następnego folderu.
Wizualizacja:

Spoilerfolder

* plik
* plikfolder

* plik
* plik
* plik
* plik
* folder
* plikNie jest to jednak aż tak potrzebne, bo pliki znajdują się w 14 folderach (w przyszłości na pewno dojdzie więcej), więc mogę to dopisać ręcznie i edytować szybciej, jednak nie liczy się czas, tylko efektywność. Jeśli przeniosę program na inny komputer, będzie łatwiej.

Wonski:
Czy zadanie to musi być wykonane przy użyciu C++?
Moim zdaniem python nadaje się do takich zadań doskonale. Używanie c++ do tego typu zadań to moim zdaniem przerost formy nad treścią.

Tak więc jeśli c++ nie jest konieczny to sugerowałbym zapoznać się z modułem pythonowym:

--- Kod: ---os.path
--- Koniec kodu ---
Jeśli idzie o wyszukiwanie konkretnych słów w pliku to tu już (jeżeli chcemy to zrobić oczywiście "jak człowiek") użyć wyrażeń regularnych, lepiej znanych jako regexy.

Jeżeli będziesz miał jakieś kłopoty z skonstruowaniem programu w pythonie to daj znać. Jeśli jednak zdecydujesz się na rozwiązanie c++ to również coś wykombinujemy.

BTW. C++17 dostarcza nam nowy moduł zarządzania plikami:
https://en.cppreference.com/w/cpp/filesystem
Co prawda nie korzystałem z tego, ale standardowe rzeczy z reguł są fajne i intuicyjne.
Jeśli dobrze pamiętam to c++ nie dostarcza funkcji odpowiedzialnych za regexy. Tak więc pozostaje rozwiązanie z bibliotek boosta (boost regex) albo ręczna manipulacja stringami.

Myślę nawet, że dałoby radę obskoczyć to zadanie bez użycia jakiegokolwiek języka programowania. Wiele IDE ma opcję "find all"/"replace all" danej frazy w całym drzewie katalogu roboczego. Czy jest to szybkie? Nigdy nie robiłem tego na takiej ilości plików, ale z pewnością jest to efektywne rozwiązanie.

Bogdan Zwei:
Jako tako jedynie gdzie programowałem to C++, więc dlatego napisałem o tym. Zapoznam się a Pythonem, jak znajdę czas i w razie pytań/problemów napiszę tutaj.

Dzięki!

Wonski:
Jeszcze co do rozwiązania nieprogramistycznego to przyjemnie idzie załatwić to jednym poleceniem z konsoli:

--- Kod: ---grep -rnwl . -e "coSzukam" | xargs sed -i 's|coSzukam|naCoZamieniam|g'
--- Koniec kodu ---

"Kropka" po -rnwl powoduje, że komenda jest wykonywana rekursywnie w wszystkich podkatalogach.
Polecenie to wyszukuje frazy "coSzukam" i zamienia ją na "naCoZamieniam".
Składnia regex, więc możesz to dowolnie modyfikować by wyszukiwało inne wzorce.

Komendę tą można również bez problemu odpalić pod windowsem, jeśli masz zainstalowany jakiś terminal typu git bash (instalowany defaultowo wraz z samym gitem).

Moim zdaniem jest to zdecydowanie najszybsze, najbardziej optymalne a przy tym najprostsze możliwe rozwiązanie tego problemu.

edit
Jeżeli zmianom mają podlegać tylko pliki o określonych rozszerzeniach, bądź ich nazwy mają spełniać określone kryteria (napisane przy użyciu regexów) to możesz jeszcze bardziej przyspieszyć wykonanie tego polecenie poprzez dodanie po prostu:

--- Kod: --- --include="jakas_nazwa"\*.{cpp,hpp,albo_dowolne_inne_rozszerzenie}
--- Koniec kodu ---

Więc wynikowe polecenie będzie wyglądać następująco:

--- Kod: ---grep -rnwl --include="jakas_nazwa"\*.{cpp,hpp,albo_dowolne_inne_rozszerzenie} . -e "coSzukam" | xargs sed -i 's|coSzukam|naCoZamieniam|g'
--- Koniec kodu ---

Case sensitive w grepie wyłącza się przy pomocy flag:

--- Kod: --- -i, -y, --ignore-case
--- Koniec kodu ---

Resztę już sam powinieneś ogarnąć a jeśli nie to daj znać.

Nawigacja

[0] Indeks wiadomości

Idź do wersji pełnej