Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!
Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.
Witam ponownie po wielu latach przerwy:)
Muszę przerobić ponad 400 plików - należy w nich zamienić fragmenty tekstów.
W plikach pdf może pojawić się taki fragment (wiele razy, raz, w ogóle):
Fragment 1
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_322', 15259]); } catch(e) { console.println(e); } };
Chciałbym za każdym razem odnaleźć cyfry (zarówno arabskie, jak i rzymskie, ale przyjmijmy dla prostoty, że 0-9) w części 'pp_xxx', w przykładzie jest to 322. Na moje niewprawne oko na początek trzeba będzie znaleźć sposób na odnalezienie tej cyfry. Po wielu bólach wpadłem na coś takiego (samodzielnie, więc pewnie z błędami, ale wygląda, że jest OK):
(?<=pp_)\d+(?:\'\d+)?
Kolejny krok to zastąpienie Fragmentu 1 tym:
Fragment 2
this.zoomType = zoomtype.pref; this.pageNum = 322-16;
(322-16 - chodzi mi tutaj o wynik odejmowania). I tutaj się moje umiejętności się kończą.
Podsumowując, potrzebuję pomocy przy skrypcie, który znajduje odpowiednią cyfrę z Fragment 1 plikach w określonym katalogu i wstawia ją po modyfikacji (odjęciu od niej liczby 16) do Fragment 2 i zapisuje tak zmieniony plik.
Pozdrawiam
Ostatnio edytowany przez menteith (2014-10-29 17:37:57)
Offline
Bash i Sed do plików PDF?
Pierwszy raz słyszę radziłbym jednak zajrzeć do jakiegoś języka programowania, Pythona lub Perla.
Pozdro
;-)
Offline
Rozpakowany plik pdf jest plikiem tekstowym, można go edytować jak inny plik. Dlatego właśnie padło na bash, siedziałem nad innymi opcjami. Dla prosty pousuwam informacje o plikach pdf z pierwszego postu.
Offline
Weź perla - ułatwisz sobie życie i oszczędzisz czas. Otwierasz plik, przeczesujesz go linia po linii, szukasz linii która zawiera dany zestaw znaków, wygrzebujesz z niej dowolną ilość wystąpień cyferek po "pp_" - masz mechanizm grupowania, wrzucasz do zmiennej, odejmujesz 16. Taka sama zabawa ze wstawianiem obliczonej wartości w pożądane miejsce.
Z regexami jest tak, że nieraz uzyskujesz wyniki najmniej spodziewane więc lepiej dopieścić je maksymalnie pod względem szczegółów - to pozwoli uzyskać większą dokładność. Zwłaszcza na początku jeśli brak Ci wprawy to lepiej zbuduj takiego regexa żeby ci przypadkowych wartości nie skosiło. Oczywiście wszystko zależy od specyfiki tekstu - powtarzalności fragmentów, różnorodności itp. Tj. mniejsze prawdopodobieństwo że wykosisz śmieci kiedy masz jeden listing, niż kiedy masz ich np. sto, bo nie jesteś w stanie przewidzieć jak to się zachowa (w tym przypadku im więcej tekstu w języku naturalnym tym mniejsze pr-stwo błędu). Pracowałam nad przetwarzaniem kodów źródłowych 3 miesiące - perl świetnie dają radę ;)
w necie masa tooli typu regextester - polecam ćwiczyć, przydatne w sytuacji kiedy puszczanie skryptu i przeglądanie wyników zajmuje trochę czasu. Tam wrzucasz testowany tekst i tworzysz regexa, potem taki regex wędruje na "produkcję" - kiedy jesteś już w miarę pewien co do tego jak się parserek z takim regexem zachowa.
Jak gdzieś znajdę to podrzucę szkielet skryptu.
pzdr.
Ostatnio edytowany przez Trin (2014-10-29 20:41:07)
Offline
Czy zmieniony fragment pliku musi wyglądać tak?
this.zoomType = zoomtype.pref; this.pageNum = 322-16;
czy tak?
this.zoomType = zoomtype.pref; this.pageNum = 306;
==========================
W takim razie będą dwie wersje:
Zawartość pliku:
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_322', 15259]); } catch(e) { console.println(e); } }; this.zoomType = zoomtype.pref; this.pageNum = 322-16;
1.
pic@pic:~/Desktop/test$ awk 'match($0,/_/){x=substr($0,RSTART+RLENGTH,3)}/this.pageNum =/{gsub(/=.*/,"= "x-16)}1' a if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_322', 15259]); } catch(e) { console.println(e); } }; this.zoomType = zoomtype.pref; this.pageNum = 306 pic@pic:~/Desktop/test$
2.
pic@pic:~/Desktop/test$ awk 'match($0,/_/){x=substr($0,RSTART+RLENGTH,3)}/this.pageNum =/{gsub(/=.*/,"= "x"-16")}1' a if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_322', 15259]); } catch(e) { console.println(e); } }; this.zoomType = zoomtype.pref; this.pageNum = 322-16 pic@pic:~/Desktop/test$
Ostatnio edytowany przez prosze (2014-10-30 13:27:58)
Offline
Dziękuję Wam bardzo za odpowiedzi. No to po kolei.
Trin
Trin napisał(-a):
Weź perla - ułatwisz sobie życie i oszczędzisz czas.
No właśnie przeczesując Internet widziałem dużo opcji związanych z perlem właśnie.
Trin napisał(-a):
Z regexami jest tak, że nieraz uzyskujesz wyniki najmniej spodziewane więc lepiej dopieścić je maksymalnie pod względem szczegółów
Trin napisał(-a):
w necie masa tooli typu regextester - polecam ćwiczyć, przydatne w sytuacji kiedy puszczanie skryptu i przeglądanie wyników zajmuje trochę czasu.
Ten mój regexp właśnie ćwiczyłem na takm toolu - nie wyłapałem błędu, ale to nie oznacza, że go nie ma, a ryzykować niezbyt chcę.
Trin napisał(-a):
Jak gdzieś znajdę to podrzucę szkielet skryptu.
To jak znajdziesz to będzie super. Kiedyś przerabiałem kod perlowy który z plików jpg robił pdf - obsługiwał katalog podany jako argument. Pewnie się kiedyś przyda.
prosze, wielkie dzieki za kod i pomoc! Nie zawsze jestem w stanie odpowiedzieć od razu, dlatego przepraszam za opoóźnienie:) Chodziło mi o to:
this.zoomType = zoomtype.pref; this.pageNum = 306;
Jak przerobić Twój skrypt, żeby oprócz cyfr w postaci 0-9 obsługiwał także rzymskie (I, IV, X, XII itd.) - odejmował od nich 2, a przypadku pp_Cover lub pp_C odejmował 1?
Dziękuję jeszcze raz:)
Offline
menteith napisał(-a):
Jak przerobić Twój skrypt, żeby oprócz cyfr w postaci 0-9 obsługiwał także rzymskie (I, IV, X, XII itd.) - odejmował od nich 2, a przypadku pp_Cover lub pp_C odejmował 1?
A to już wyższa szkoła jazdy ;) Ale podobno jest do tego odpowiedni cpan
Ewentualnie wynajdywanie koła na nowo, i konwersja rzymskie-->arabskie-->odejmowanie-->rzymskie
Offline
Ta konwersja do zrobienia w sumie, bo zakres liczb rzymskich to I-XX. I regex (niestety, bo jak zauważyłą Trin) łatwo o blędy. Tutaj parę informacji o regexie i liczbach rzymskich
http://stackoverflow.com/questions/267399/how-do-yo … ar-expression
Offline
winnetou napisał(-a):
menteith napisał(-a):
Jak przerobić Twój skrypt, żeby oprócz cyfr w postaci 0-9 obsługiwał także rzymskie (I, IV, X, XII itd.) - odejmował od nich 2, a przypadku pp_Cover lub pp_C odejmował 1?
A to już wyższa szkoła jazdy ;) Ale podobno jest do tego odpowiedni cpan
Ewentualnie wynajdywanie koła na nowo, i konwersja rzymskie-->arabskie-->odejmowanie-->rzymskie
Czy poza prokreacją, znasz jakąś rzecz, do której nie ma modułu Perla? :D
Bo chyba nie jest ich zbyt wiele..... xD
Offline
To podaj fragment pliku wejściowego z cyframi rzymskimi oraz napisz jakiego wyniku oczekujesz .
Ostatnio edytowany przez prosze (2014-10-30 19:52:04)
Offline
Pierwsza możliwość to cyfry arabskie - Fragment 1.
Druga możliwość, czyli cyfry rzymskie (to samo co dla arabskich, tylko cyfra po pp_ jest rzymska):
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_vii', 15259]); } catch(e) { console.println(e); } };
A na wyjściu:
this.zoomType = zoomtype.pref; this.pageNum = vii-2;
this.pageNum = vii-2 - tutaj wynik pisany cyframi arabskimi, czyli powinno być this.pageNum = 5, a więc
this.zoomType = zoomtype.pref; this.pageNum = 5;
Trzecia możliwość: pp_C lub pp_Cover:
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_Cover', 15259]); } catch(e) { console.println(e); } };
A na wyjściu:
this.zoomType = zoomtype.pref; this.pageNum = 0;
Tutaj na wyjściu zawsze 0.
Plików do zmiany jest 497, a wystąpień kodu w plikach jest łącznie 3112 - fajnie gdyby skrypt pokazywał ile przerobił dla rzymskich, arabskich i dla pp_Cover - wtedy łatwiej sprawdzić, czy coś były jakieś błędy. I może być także zamiastu kodu dla bash, perl, tak jak sugerowała Trin. Dla perla mam kod otwierający wszystkie pliki pdf w katalogu, jeśli to w czymś pomoże. Z góry dziekuje.
EDIT.
http://www.unix.com/shell-programming-and-scripting … numerals.html
Tutaj jest informacja o konwersji arabic-roman.
Ostatnio edytowany przez menteith (2014-10-30 23:51:32)
Offline
menteith napisał(-a):
Rozpakowany plik pdf jest plikiem tekstowym, można go edytować jak inny plik. Dlatego właśnie padło na bash, siedziałem nad innymi opcjami. Dla prosty pousuwam informacje o plikach pdf z pierwszego postu.
Kolejne pytanie. Czy to są pliki .pdf, czy .txt? Jeżeli są to pliki .txt to podaj wynik poniższego polecenia:
for x in *; do awk '/pp_|this.pageNum/' "$x"; done > wynik.txt
Plik o nazwie "wynik.txt" zapodaj na darmowy hosting plików.
Offline
U mnie tworzy się pusty plik. Przykładowe pliki znajdują się tutaj:
http://pl.rghost.net/58815529
A moje pliki, to są pdfy, które są rozpakowane za pomocą narzędzia pdftk.
Uncompress PDF page streams for editing the PDF in a text editor (e.g., vim, emacs)
pdftk doc.pdf output doc.unc.pdf uncompress
Więcej info https://www.pdflabs.com/docs/pdftk-cli-examples/.
Ostatnio edytowany przez menteith (2014-10-31 18:28:56)
Offline
Powyższe polecenie zadziała tylko do plików tekstowych, czyli w pierwszej kolejności należy przeprowadzić konwersję plików .pdf do .txt.
Offline
Chodzi o rozszerzenie? Bo zmieniłem z .pdf na .txt i brak reakcji.
Offline
menteith napisał(-a):
Chodzi o rozszerzenie? Bo zmieniłem z .pdf na .txt i brak reakcji.
Konwersja != zmianie rozszerzenia
na przykład: http://linux.die.net/man/1/pdftotext
pzdr
Ostatnio edytowany przez Trin (2014-10-31 20:07:18)
Offline
No właśnie zdaję sobie z tego sprawę. Tylko konwersja do "czystego tekstu" mi niewiele daje - nie będzie tam tekstu, który chcę zmienić. Potrzebny jest bowiem kod JavaScript linków, dzięki którym mogę przeskakiwać z jednej strony do drugiej. Rozkompresowanie pdfa narzędziem pdftk umożliwia traktowanie go jako zwykłego pliku tekstowego i wtedy JavaScript jest widoczny np. w notatniku. W skompresowanym pliku pdf (tak jest standardowo) kod JavaScript nie jest widoczny. A chodzi przecież o modyfikację "zaszytego" w pdfie kodu JavaScript, a nie tekstu widocznego na ekranie. Mam nadzieję, że teraz wszystko wyjaśniłem.
Ostatnio edytowany przez menteith (2014-10-31 20:15:03)
Offline
No dobra. Znalazłam.
Bardzo podstawowy szkielet - zbędne części wycięłam.
use warnings; use strict; our @array = `find -P $path -type f -name \'*.h\'`; #tu sobie zrob jakiegos finda po tych twoich plikach foreach my $p (@array){ open(my $source, $p) or die "Nie udalo sie otworzyc pliku"; while(my $line = <$source>){ if($line =~ /regex/){ #tutaj operujesz na tym co znajdziesz, zapisujesz do $1 - wystarczy podstawowy help do perla. } close($source); }
pzdr
Ostatnio edytowany przez Trin (2014-10-31 21:13:49)
Offline
Aniołku, między perlobashem a perlem jest maleńka różnica. xD
http://perldoc.perl.org/File/Find.html
http://www.perlmonks.org/?node_id=217166
Pozdro
;-)
Ostatnio edytowany przez Jacekalex (2014-10-31 23:18:40)
Offline
Jacekalex napisał(-a):
Aniołku, między perlobashem a perlem jest maleńka różnica. xD
http://perldoc.perl.org/File/Find.html
http://www.perlmonks.org/?node_id=217166
Pozdro
;-)
hm, to mnie zagiąłeś - powinnam się bardzo wstydzić?
Offline
Nie wstydzić, ale jak już uchwyt pliku robisz prawidłowo w Perlu, to poszukać plików też można z poziomu Perla, co jest o tyle ciekawe, że w akcjach typu tworzenie drzewa katalogów czy szukanie plików Perl zazwyczaj jest 2 -7 razy szybszy od Basha.
Co innego tak zapinać np Snorta, jeśli chcemy parsować jego logi przy pomocy perlowych regexów (wersja >=2.9 zapisuje logi binarne, lub wypluwa na konsolę normalne po użyciu opcji -A), ale find, to lekka przesada.
Ostatnio edytowany przez Jacekalex (2014-10-31 23:45:57)
Offline
menteith napisał(-a):
Chodzi o rozszerzenie? Bo zmieniłem z .pdf na .txt i brak reakcji.
Zrób tak. Rozpakuj jeden przykładowy plik .pdf w którym chcesz coś zmienić.
pdftk nazwa_twojego_pliku_pdf output plik_rozpakowany.pdf uncompress
Następnie rozpakowany plik .pdf zapodaj na darmowy hosting plików. Chodzi o to, aby zobaczyć jak on wygląda po rozpakowaniu.
Offline
Offline
W pliku, który pokazałeś fragment 1 pojawił się 245 razy. Sprawdzisz to poleceniem
awk '/pp_/{a++; print $0, a}' 473_uncompressed.pdf
Natomiast fragmentu 2 w tym pliku nie ma
awk '/pageNum/' 473_uncompressed.pdf
Jeżeli możesz to zapodaj plik, który zawiera fragment 1 i fragment 2.
Offline
Fragment 2, to jest to co chcę otrzymać - tego nie ma w pliku, a ma być zamiast Fragment 1.
Dla jasności napiszę jeszcze raz. Po pp_ mogą być 3 możliwości.
Pierwsza możliwość to cyfry arabskie - wtedy chciałbym, że od przykładowo 322 (pp_322) odjęto 16, czyli żeby wyszło: pp_306.
Pierwsza możliwość
czego szukam
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_322', 15259]); } catch(e) { console.println(e); } };
Który chciałbym zastąpić takim oto kodem:
to, co chciałbym żeby było
this.zoomType = zoomtype.pref; this.pageNum = 306;
Druga możliwość to po pp_ liczby rzymskie. Chciałbym żeby od przykładowo vii (pp_vii) odjęto 2 i żeby wyszło: pp_5.
Druga możliwość
czego szukam
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_vii', 15259]); } catch(e) { console.println(e); } };
to, co chciałbym żeby było
this.zoomType = zoomtype.pref; this.pageNum = vii-2;
this.pageNum = vii-2 - tutaj wynik pisany cyframi arabskimi, czyli powinno być this.pageNum = 5, a więc ostatecznie chciałbym to:
this.zoomType = zoomtype.pref; this.pageNum = 5;
Trzecia możliwość: pp_C lub pp_Cover:
Trzecia możliwość
czego szukam
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_Cover', 15259]); } catch(e) { console.println(e); } };
co chciałbym, żeby było
this.zoomType = zoomtype.pref; this.pageNum = 0;
Ostatnio edytowany przez menteith (2014-11-02 16:40:52)
Offline