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):
[i]Fragment 1[/i]
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_[b]xxx[/b]', w przykładzie jest to [b]322[/b]. 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 [i]Fragmentu 1[/i] tym:
[i]Fragment 2[/i]
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 [i]Fragment 1[/i] plikach w określonym katalogu i wstawia ją po modyfikacji (odjęciu od niej liczby 16) do [i]Fragment 2[/i] 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 [url=http://www.perlmonks.org/?node_id=583813]Perla[/url].
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.
[b]Trin[/b]
[quote=Trin]Weź perla - ułatwisz sobie życie i oszczędzisz czas.[/quote]
No właśnie przeczesując Internet widziałem dużo opcji związanych z perlem właśnie.
[quote=Trin]Z regexami jest tak, że nieraz uzyskujesz wyniki najmniej spodziewane więc lepiej dopieścić je maksymalnie pod względem szczegółów[/quote]
[quote=Trin]w necie masa tooli typu regextester - polecam ćwiczyć, przydatne w sytuacji kiedy puszczanie skryptu i przeglądanie wyników zajmuje trochę czasu.[/quote]
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ę.
[quote=Trin]Jak gdzieś znajdę to podrzucę szkielet skryptu.[/quote]
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.
[b]prosze[/b], 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
[quote=menteith]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?[/quote]
A to już wyższa szkoła jazdy ;) Ale podobno jest do tego odpowiedni [url=http://search.cpan.org/~tels/Math-Roman-1.07/lib/Math/Roman.pm]cpan[/url]
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-you-match-only-valid-roman-numerals-with-a-regular-expression
Offline
[quote=winnetou][quote=menteith]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?[/quote]
A to już wyższa szkoła jazdy ;) Ale podobno jest do tego odpowiedni [url=http://search.cpan.org/~tels/Math-Roman-1.07/lib/Math/Roman.pm]cpan[/url]
Ewentualnie wynajdywanie koła na nowo, i konwersja rzymskie-->arabskie-->odejmowanie-->rzymskie[/quote]
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 - [i]Fragment 1[/i].
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ść: [u]pp_C[/u][u][/u] lub [u]pp_Cover[/u]:
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/156805-sort-roman-numerals.html
Tutaj jest informacja o konwersji arabic-roman.
Ostatnio edytowany przez menteith (2014-10-30 23:51:32)
Offline
[quote=menteith]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.[/quote]
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)[/quote]
Kod:
pdftk doc.pdf output doc.unc.pdf uncompressWięcej info [url]https://www.pdflabs.com/docs/pdftk-cli-examples/[/url].
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
[quote=menteith]Chodzi o rozszerzenie? Bo zmieniłem z .pdf na .txt i brak reakcji.[/quote]
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
[quote=Jacekalex]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
;-)[/quote]
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
[quote=menteith]Chodzi o rozszerzenie? Bo zmieniłem z .pdf na .txt i brak reakcji.[/quote]
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
Plik jest tutaj: [url]http://pl.rghost.net/private/58845357/f8f9aa9312f7e4ad311502906bf1985a[/url]
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
[i]Fragment 2[/i], to jest to co chcę otrzymać - tego nie ma w pliku, a ma być zamiast[i] Fragment 1[/i].
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.
[b]Pierwsza możliwość[/b]
[i]czego szukam[/i]
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:
[i]to, co chciałbym żeby było[/i]
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.
[b]Druga możliwość[/b]
[i]czego szukam[/i]
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_vii', 15259]); } catch(e) { console.println(e); } };
[i]to, co chciałbym żeby było[/i]
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ść: [u]pp_C[/u][u][/u] lub [u]pp_Cover[/u]:
[b]Trzecia możliwość[/b]
[i]czego szukam[/i]
if (this.hostContainer) { try { this.hostContainer.postMessage(['newPage', 'pp_Cover', 15259]); } catch(e) { console.println(e); } };
[i]co chciałbym, żeby było[/i]
this.zoomType = zoomtype.pref; this.pageNum = 0;
Ostatnio edytowany przez menteith (2014-11-02 16:40:52)
Offline
Time (s) | Query |
---|---|
0.00010 | SET CHARSET latin2 |
0.00004 | SET NAMES latin2 |
0.00120 | SELECT u.*, g.*, o.logged FROM punbb_users AS u INNER JOIN punbb_groups AS g ON u.group_id=g.g_id LEFT JOIN punbb_online AS o ON o.ident='18.118.144.98' WHERE u.id=1 |
0.00096 | REPLACE INTO punbb_online (user_id, ident, logged) VALUES(1, '18.118.144.98', 1732443321) |
0.00041 | SELECT * FROM punbb_online WHERE logged<1732443021 |
0.00055 | SELECT t.subject, t.closed, t.num_replies, t.sticky, f.id AS forum_id, f.forum_name, f.moderators, fp.post_replies, 0 FROM punbb_topics AS t INNER JOIN punbb_forums AS f ON f.id=t.forum_id LEFT JOIN punbb_forum_perms AS fp ON (fp.forum_id=f.id AND fp.group_id=3) WHERE (fp.read_forum IS NULL OR fp.read_forum=1) AND t.id=26631 AND t.moved_to IS NULL |
0.00006 | SELECT search_for, replace_with FROM punbb_censoring |
0.00318 | SELECT u.email, u.title, u.url, u.location, u.use_avatar, u.signature, u.email_setting, u.num_posts, u.registered, u.admin_note, p.id, p.poster AS username, p.poster_id, p.poster_ip, p.poster_email, p.message, p.hide_smilies, p.posted, p.edited, p.edited_by, g.g_id, g.g_user_title, o.user_id AS is_online FROM punbb_posts AS p INNER JOIN punbb_users AS u ON u.id=p.poster_id INNER JOIN punbb_groups AS g ON g.g_id=u.group_id LEFT JOIN punbb_online AS o ON (o.user_id=u.id AND o.user_id!=1 AND o.idle=0) WHERE p.topic_id=26631 ORDER BY p.id LIMIT 0,25 |
0.00143 | UPDATE punbb_topics SET num_views=num_views+1 WHERE id=26631 |
Total query time: 0.00793 s |