Sve o korišćenju regularnih izraza u programu calibre¶
Regularni izrazi koriste se na mnogim mestima u programu calibre za naprednu obradu sadržaja e-knjiga i metapodataka. Ovo uputstvo će vas postepeno uvesti u njihovu upotrebu u programu calibre.
Prvo, reč upozorenja i reč ohrabrenja¶
Ovo će, neizbežno, biti donekle tehnički - na kraju krajeva, regularni izrazi su tehnički alat za obavljanje tehničkih stvari. Moraću da koristim neki žargon i koncepte koji mogu izgledati komplikovano ili zamršeno. Pokušaću da objasnim te koncepte što jasnije mogu, ali zaista ne mogu bez njihovog korišćenja. S obzirom na to, nemojte biti obeshrabreni bilo kakvim žargonom, jer sam pokušao da objasnim sve novo. I dok sami regularni izrazi mogu izgledati kao tajanstvena, crna magija (ili, da budem prozaičniji, nasumični niz besmislenih slova i znakova), obećavam da nisu toliko komplikovani. Čak i oni koji zaista dobro razumeju regularne izraze imaju problema sa čitanjem onih složenijih, ali njihovo pisanje nije tako teško - izraz konstruišete korak po korak. Dakle, napravite korak i pratite me u zečju rupu.
Gde u calibre-u možete koristiti regularne izraze?¶
Postoji nekoliko mesta gde calibre koristi regularne izraze. Tu je Search & replace u opcijama konverzije, detekcija metapodataka iz imena fajlova u podešavanjima uvoza i Search & replace prilikom masovnog uređivanja metapodataka knjiga. Calibre uređivač knjiga takođe može koristiti regularne izraze u svojoj Search and replace funkciji. Konačno, možete koristiti regularne izraze prilikom pretrage liste knjiga u calibre-u i prilikom pretrage unutar calibre E-book pregledača.
Šta je uopšte regularni izraz?¶
Regularni izraz je način da se opišu skupovi stringova. Jedan regularni izraz može da se poklapa sa više različitih stringova. To je ono što regularne izraze čini tako moćnim -- oni su koncizan način opisivanja potencijalno velikog broja varijacija.
Белешка
Ovde koristim string u smislu u kojem se koristi u programskim jezicima: niz od jednog ili više karaktera, gde karakteri uključuju stvarna slova, brojeve, interpunkciju i takozvane praznine (prelome redova, tabulatore itd.). Imajte na umu da se generalno velika i mala slova ne smatraju istim, tako da je "a" različit karakter od "A" i tako dalje. U programu calibre, regularni izrazi nisu osetljivi na velika i mala slova u traci za pretragu, ali jesu u opcijama konverzije. Postoji način da se svaki regularni izraz učini neosetljivim na velika i mala slova, ali o tome ćemo kasnije. Postaje komplikovano jer regularni izrazi dozvoljavaju varijacije u stringovima koje poklapaju, tako da jedan izraz može da poklopi više stringova, što je razlog zašto se ljudi uopšte trude da ih koriste. Više o tome uskoro.
Možete li to da objasnite?¶
Pa, zato smo ovde. Prvo, ovo je najvažniji koncept u regularnim izrazima: Niz znakova je sam po sebi regularni izraz koji se podudara sa samim sobom. To jest, ako bih želeo da poklopim string "Hello, World!" koristeći regularni izraz, regularni izraz koji bih koristio bio bi Hello, World!. I da, zaista je tako jednostavno. Primetićete, međutim, da ovo samo poklapa tačan string "Hello, World!", a ne npr. "Hello, wOrld!" ili "hello, world!" ili bilo koju drugu takvu varijaciju.
To ne zvuči previše loše. Šta je sledeće?¶
Sledeće je početak stvarno dobrih stvari. Sećate se gde sam rekao da regularni izrazi mogu da se podudaraju sa više stringova? Ovde postaje malo komplikovanije. Recimo, kao nešto praktičnija vežba, e-knjiga koju ste hteli da konvertujete imala je gadno podnožje koje broji stranice, kao "Page 5 of 423". Očigledno bi broj stranice rastao od 1 do 423, tako da biste morali da se podudarate sa 423 različita stringa, zar ne? Pogrešno, zapravo: regularni izrazi vam omogućavaju da definišete skupove karaktera koji se podudaraju: Da biste definisali skup, stavljate sve karaktere koje želite da budu u skupu u uglaste zagrade. Tako bi se, na primer, skup [abc] podudarao sa karakterom "a", "b" ili "c". Skupovi će se uvek podudarati samo sa jednim od karaktera u skupu. Oni "razumeju" opsege karaktera, to jest, ako biste želeli da se podudarate sa svim malim slovima, koristili biste skup [a-z] za mala i velika slova koristili biste [a-zA-Z] i tako dalje. Shvatate ideju? Dakle, očigledno, koristeći izraz Page [0-9] of 423 mogli biste da se podudarate sa prvih 9 stranica, čime biste smanjili potrebne izraze na tri: Drugi izraz Page [0-9][0-9] of 423 bi se podudarao sa svim dvocifrenim brojevima stranica, a siguran sam da možete da pogodite kako bi izgledao treći izraz. Da, samo napred. Zapišite ga.
Hej, super! Ovo počinje da ima smisla!¶
Nadao sam se da ćete to reći. Ali pripremite se, sada postaje još bolje! Upravo smo videli da koristeći skupove, možemo da se podudaramo sa jednim od nekoliko karaktera odjednom. Ali možete čak i da ponovite karakter ili skup, smanjujući broj izraza potrebnih za rešavanje gornjeg primera broja stranice na jedan. Da, JEDAN! Uzbuđeni? Trebalo bi da budete! To funkcioniše ovako: Neki takozvani specijalni karakteri, "+", "?" i "*", ponavljaju jedan element koji im prethodi. (Element znači ili jedan karakter, skup karaktera, escape sekvencu ili grupu (o ova poslednja dva ćemo učiti kasnije) - ukratko, bilo koji pojedinačni entitet u regularnom izrazu). Ovi karakteri se nazivaju džokeri ili kvantifikatori. Da budemo precizniji, "?" se podudara sa 0 ili 1 prethodnog elementa, "*" se podudara sa 0 ili više prethodnog elementa i "+" se podudara sa 1 ili više prethodnog elementa. Nekoliko primera: Izraz a? bi se podudarao ili sa "" (što je prazan string, nije strogo korisno u ovom slučaju) ili sa "a", izraz a* bi se podudarao sa "", "a", "aa" ili bilo kojim brojem slova a u nizu, i, konačno, izraz a+ bi se podudarao sa "a", "aa" ili bilo kojim brojem slova a u nizu (Napomena: ne bi se podudarao sa praznim stringom!). Ista stvar važi i za skupove: Izraz [0-9]+ bi se podudarao sa svakim celim brojem koji postoji! Znam šta mislite, i u pravu ste: Ako to iskoristite u gornjem slučaju podudaranja brojeva stranica, zar to ne bi bio jedini izraz koji bi se podudarao sa svim brojevima stranica? Da, izraz Page [0-9]+ of 423 bi se podudarao sa svakim brojem stranice u toj knjizi!
Белешка
Napomena o ovim kvantifikatorima: Oni generalno pokušavaju da se podudaraju sa što je moguće više teksta, pa budite oprezni kada ih koristite. Ovo se naziva "pohlepno ponašanje" - siguran sam da shvatate zašto. Postaje problematično kada, recimo, pokušate da se podudarate sa oznakom (tagom). Uzmite u obzir, na primer, string "<p class="calibre2">Title here</p>" i recimo da želite da se podudarate sa početnom oznakom (deo između prvog para uglastih zagrada, malo više o oznakama kasnije). Pomislili biste da bi se izraz <p.*> podudarao sa tom oznakom, ali zapravo, on se podudara sa celim stringom! (Karakter "." je još jedan specijalni karakter. On se podudara sa bilo čim osim preloma reda, tako da bi se, u osnovi, izraz .* podudarao sa bilo kojom pojedinačnom linijom koje možete da se setite). Umesto toga, pokušajte da koristite <p.*?> što čini kvantifikator "*" nepohlepnim. Taj izraz bi se podudarao samo sa prvom početnom oznakom, kao što je i zamišljeno. Zapravo postoji još jedan način da se ovo postigne: Izraz <p[^>]*> će se podudarati sa istom početnom oznakom - videćete zašto nakon sledećeg odeljka. Samo imajte na umu da prilično često postoji više od jednog načina da se napiše regularni izraz.
Pa, ovi specijalni karakteri su veoma zgodni i sve to, ali šta ako želim da se poklopi tačka ili upitnik?¶
Naravno da to možete uraditi: Samo stavite obrnutu kosu crtu ispred bilo kog specijalnog karaktera i on će biti interpretiran kao doslovni karakter, bez ikakvog specijalnog značenja. Ovaj par obrnute kose crte praćen jednim karakterom naziva se escape sekvenca, a čin stavljanja obrnute kose crte ispred specijalnog karaktera naziva se izdvajanje tog znaka obrnutom kosom crtom. Escape sekvenca se interpretira kao jedan element. Postoje naravno escape sekvence koje rade i druge namene, osim izdvajanja posebnih znakova, na primer "\t" znači tabulator. Doći ćemo do nekih escape sekvenci kasnije. Oh, i usput, što se tiče tih specijalnih karaktera: Smatrajte svaki karakter o kojem raspravljamo u ovom uvodu kao da ima neku funkciju da bude specijalan i stoga ga treba označiti obrnutom kosom crtom ako želite doslovni karakter.
Dakle, koji su najkorisniji skupovi?¶
Znao sam da ćete pitati. Neki korisni skupovi su [0-9] koji se poklapa sa jednim brojem, [a-z] koji se poklapa sa jednim malim slovom, [A-Z] koji se poklapa sa jednim velikim slovom, [a-zA-Z] koji se poklapa sa jednim slovom i [a-zA-Z0-9] koji se poklapa sa jednim slovom ili brojem. Takođe možete koristiti escape sekvencu kao skraćenicu:
\dje ekvivalentno sa
[0-9]\wje ekvivalentno sa
[a-zA-Z0-9_]\sodgovara bilo kom belom znaku
Белешка
Beli znak je znak koji se ne štampa. Tu spadaju razmak, tabulator, znak za novi red, znak za novu stranicu, povratak na početak reda, nerazdvojivi razmak i drugi slični znakovi.
Белешка
Skupovi velikih i malih slova mogu se podudarati i sa velikim i sa malim slovima ako je omogućena postavka da pretrage ne razlikuju velika i mala slova. Takve postavke se nalaze, na primer, u Podešavanja->Pretraga u samom calibre-u i na panelu za pretragu u calibre E-book viewer-u, kao i u calibre alatu Edit book.
Kao poslednja napomena o skupovima, takođe možete definisati skup kao bilo koji karakter osim onih u skupu. To radite tako što uključite karakter "^" kao potpuno prvi karakter u skupu. Tako bi se [^a] poklapao sa bilo kojim karakterom osim "a". To se zove komplementiranje skupa. Te prečice za izlazne sekvence koje smo ranije videli takođe mogu biti komplementirane: "\D" znači bilo koji karakter koji nije broj, što je ekvivalentno sa [^0-9]. Ostale prečice mogu biti komplementirane, pogađate, korišćenjem odgovarajućeg velikog slova umesto malog. Dakle, vraćajući se na primer <p[^>]*> iz prethodnog odeljka, sada možete videti da skup karaktera koji koristi pokušava da se poklopi sa bilo kojim karakterom osim zatvorene ugaone zagrade.
Ali ako bih imao nekoliko različitih stringova koje želim da poklopim, stvari postaju komplikovane?¶
Ne bojte se, život je i dalje dobar i lak. Razmotrite ovaj primer: Knjiga koju konvertujete ima napisano "Title" na svakoj neparnoj stranici i "Author" na svakoj parnoj stranici. Izgleda odlično u štampi, zar ne? Ali u e-knjigama, to je iritantno. Možete grupisati cele izraze u obične zagrade, a karakter "|" će vam omogućiti da poklopite ili izraz sa njegove desne strane ili onaj sa leve. Kombinujte to i gotovi ste. Prebrzo za vas? U redu, prvo, grupišemo izraze za neparne i parne stranice, dobijajući tako (Title)(Author) kao naša dva potrebna izraza. Sada pojednostavljujemo stvari korišćenjem vertikalne crte ("|" se zove karakter vertikalne crte): Ako koristite izraz (Title|Author) dobićete poklapanje za "Title" (na neparnim stranicama) ili ćete poklopiti "Author" (na parnim stranicama). Pa, zar to nije bilo lako?
Možete, naravno, koristiti vertikalnu crtu i bez korišćenja zagrada za grupisanje. Sećate se kada sam rekao da kvantifikatori ponavljaju element koji im prethodi? Pa, vertikalna crta radi malo drugačije: Izraz "Title|Author" će se takođe poklopiti ili sa stringom "Title" ili sa stringom "Author", baš kao u gornjem primeru sa grupisanjem. Vertikalna crta bira između celog izraza koji joj prethodi i koji sledi. Dakle, ako biste želeli da poklopite stringove "Calibre" i "calibre" i želeli da birate samo između velikog i malog slova "c", morali biste da koristite izraz (c|C)alibre, gde grupisanje osigurava da će samo "c" biti izabrano. Ako biste koristili c|Calibre, dobili biste poklapanje sa stringom "c" ili sa stringom "Calibre", što nije ono što smo želeli. Ukratko: Ako ste u nedoumici, koristite grupisanje zajedno sa vertikalnom crtom.
Propustili ste...¶
... sačekajte samo minut, postoji još jedna, zaista sjajna stvar koju možete uraditi sa grupama. Ako imate grupu koju ste prethodno uparili, možete koristiti reference na tu grupu kasnije u izrazu: Grupe su numerisane počevši od 1, a na njih upućujete tako što ispred broja grupe stavite obrnutu kosu crtu, tako bi se peta grupa referencirala kao \5. Dakle, ako ste tražili ([^ ]+) \1 u nizu "Test Test", pronašli biste podudaranje za ceo niz!
Na početku ste rekli da postoji način da se regularni izraz učini neosetljivim na velika i mala slova?¶
Da, jesam, hvala što ste obratili pažnju i podsetili me. Možete reći calibre-u kako želite da se određene stvari obrađuju koristeći nešto što se zove zastavice (flags). Zastavice uključujete u svoj izraz koristeći specijalnu konstrukciju (?flags go here) gde biste, očigledno, zamenili "flags go here" sa specifičnim zastavicama koje želite. Za ignorisanje veličine slova, zastavica je i, tako da uključujete (?i) u svoj izraz. Tako bi (?i)test uparilo "Test", "tEst", "TEst" i bilo koju varijaciju veličine slova koje biste mogli da se setite.
Još jedna korisna zastavica omogućava da tačka odgovara bilo kom karakteru, uključujući novi red, zastavica s. Ako želite da koristite više zastavica u izrazu, samo ih stavite u isti iskaz: (?is) bi ignorisalo veličinu slova i učinilo da tačka odgovara svemu. Nije bitno koju zastavicu navedete prvu, (?si) bi bilo ekvivalentno gore navedenom.
Mislim da počinjem da razumem ove regularne izraze sada... kako da ih koristim u calibre-u?¶
Konverzije¶
Počnimo sa podešavanjima konverzije, što je zaista sjajno. U delu Search & replace, možete uneti regexp (skraćenica za regularni izraz) koji opisuje string koji će biti zamenjen tokom konverzije. Sjajan deo je čarobnjak. Kliknite na štap čarobnjaka i dobićete pregled onoga što calibre "vidi" tokom procesa konverzije. Pomerite se naniže do stringa koji želite da uklonite, izaberite ga i kopirajte, nalepite ga u regexp polje na vrhu prozora. Ako postoje promenljivi delovi, kao što su brojevi stranica ili slično, koristite skupove i kvantifikatore da ih pokrijete, i dok ste već tu, ne zaboravite da posebne znakove označite obrnutom kosom crtom, ako ih ima. Pritisnite dugme sa oznakom Test i calibre će istaći delove koje bi zamenio da koristite taj regexp. Kada ste zadovoljni, pritisnite OK i konvertujte. Budite oprezni ako vaš izvor konverzije ima tagove kao u ovom primeru:
Maybe, but the cops feel like you do, Anita. What's one more dead vampire?
New laws don't change that. </p>
<p class="calibre4"> <b class="calibre2">Generated by ABC Amber LIT Conv
<a href="http://www.processtext.com/abclit.html" class="calibre3">erter,
http://www.processtext.com/abclit.html</a></b></p>
<p class="calibre4"> It had only been two years since Addison v. Clark.
The court case gave us a revised version of what life was
(besramno izvučeno iz ove teme). Moraćete da uklonite i neke od oznaka. U ovom primeru, preporučio bih da počnete sa oznakom <b class="calibre2">, sada morate da završite sa odgovarajućom zatvarajućom oznakom (otvarajuće oznake su <tag>, zatvarajuće oznake su </tag>), što je jednostavno sledeće </b> u ovom slučaju. (Pogledajte dobar HTML priručnik ili pitajte na forumu ako vam ovo nije jasno). Otvarajuća oznaka se može opisati koristeći <b.*?>, zatvarajuća oznaka koristeći </b>, tako da bismo mogli da uklonimo sve između tih oznaka koristeći <b.*?>.*?</b>. Ali korišćenje ovog izraza bi bila loša ideja, jer uklanja sve što je obuhvaćeno <b>- oznakama (koje, usput, prikazuju obuhvaćeni tekst podebljano), i velika je verovatnoća da ćemo na ovaj način ukloniti delove knjige. Umesto toga, uključite i početak obuhvaćenog niza, čineći regularni izraz <b.*?>\s*Generated\s+by\s+ABC\s+Amber\s+LIT.*?</b> \s sa kvantifikatorima su uključeni ovde umesto eksplicitnog korišćenja razmaka kao što se vidi u nizu da bi se uhvatile sve varijacije niza koje bi se mogle pojaviti. Ne zaboravite da proverite šta će calibre ukloniti da biste bili sigurni da nećete ukloniti delove koje želite da zadržite ako testirate novi izraz. Ako proverite samo jedno pojavljivanje, možda ćete propustiti nepoklapanje negde drugde u tekstu. Takođe imajte na umu da ako slučajno uklonite više ili manje oznaka nego što ste zapravo želeli, calibre pokušava da popravi oštećeni kôd nakon uklanjanja.
Dodavanje knjiga¶
Još jedna stvar za koju možete koristiti regularne izraze je izdvajanje metapodataka iz imena datoteka. Ovu funkciju možete pronaći u delu "Dodavanje knjiga" u podešavanjima. Ovde postoji posebna funkcija: Možete koristiti imena polja za polja metapodataka, na primer (?P<title>) bi označavalo da calibre koristi ovaj deo niza kao naslov knjige. Dozvoljena imena polja su navedena u prozorima, zajedno sa još jednim lepim poljem za testiranje. Primer: Recimo da želite da uvezete gomilu datoteka sa imenima poput Classical Texts: The Divine Comedy by Dante Alighieri.mobi. (Očigledno, ovo je već u vašoj biblioteci, pošto svi volimo klasičnu italijansku poeziju) ili Science Fiction epics: The Foundation Trilogy by Isaac Asimov.epub. Ovo je očigledno šema imenovanja iz koje calibre neće izvući nikakve smislene podatke - njegov standardni izraz za izdvajanje metapodataka je (?P<title>.+) - (?P<author>[^_]+). Regularni izraz koji bi ovde radio bio bi [a-zA-Z]+: (?P<title>.+) by (?P<author>.+). Imajte na umu da, unutar grupe za polje metapodataka, morate koristiti izraze da opišete šta polje zapravo poklapa. Takođe imajte na umu da, kada koristite polje za testiranje koje calibre pruža, morate dodati ekstenziju datoteke vašem imenu datoteke za testiranje, inače nećete dobiti nikakva poklapanja, uprkos korišćenju ispravnog izraza.
Grupno uređivanje metapodataka¶
Poslednji deo je regularni izraz Search and replace u poljima metapodataka. Ovome možete pristupiti tako što ćete izabrati više knjiga u biblioteci i koristiti grupno uređivanje metapodataka. Budite veoma oprezni kada koristite ovu poslednju funkciju, jer može učiniti veoma loše stvari vašoj biblioteci! Dvaput proverite da li vaši izrazi rade ono što želite koristeći polja za testiranje, i označite samo knjige koje zaista želite da promenite! U režimu pretrage regularnih izraza, možete pretraživati u jednom polju, zameniti tekst nečim i čak upisati rezultat u drugo polje. Praktičan primer: Recimo da vaša biblioteka sadrži knjige iz serijala Dina Frenka Herberta, nazvane na način Dune 1 - Dune, Dune 2 - Dune Messiah i tako dalje. Sada želite da dobijete Dune u polju serijala. To možete uraditi pretraživanjem (.*?) \d+ - .* u polju naslova i zamenom sa \1 u polju serijala. Vidite šta sam tu uradio? To je referenca na prvu grupu kojom zamenjujete polje serijala. Sada kada ste podesili serijal, potrebno je samo da uradite još jednu pretragu za .*? - u polju naslova i zamenite ga sa "" (prazan niz), ponovo u polju naslova, i vaši metapodaci su uredni i čisti. Zar to nije sjajno? Usput, umesto da zamenite celo polje, možete takođe dodati na kraj ili početak polja, tako da, ako ste želeli da naslovu knjige bude dodat info o serijalu na početku, mogli biste i to da uradite. Kao što ste do sada nesumnjivo primetili, postoji polje za potvrdu sa oznakom Case sensitive, tako da nećete morati da koristite zastavice da biste izabrali ponašanje ovde.
Pa, to bi otprilike zaključilo veoma kratak uvod u regularne izraze. Nadam se da sam vam pokazao dovoljno da barem počnete i da vam omogućim da nastavite učenje sami - dobra polazna tačka bi bila Python dokumentacija za regularne izraze.
Još jedna poslednja reč upozorenja: Regularni izrazi su moćni, ali je takođe veoma lako pogrešiti. calibre pruža zaista odlične mogućnosti testiranja da vidite da li se vaši izrazi ponašaju onako kako očekujete. Koristite ih. Pokušajte da ne pucate sebi u nogu. (Bože, obožavam taj izraz...). Ali ako, uprkos upozorenju, povredite nogu (ili bilo koji drugi deo tela), pokušajte da naučite iz toga.
Kratak pregled¶
Zasluge¶
Hvala na pomoći sa savetima, ispravkama i slično:
ldolse
kovidgoyal
chaley
dwanthny
kacir
Starson17
Orpheu
Za više o regularnim izrazima pogledajte The Python User Manual. Stvarna biblioteka regularnih izraza koju koristi calibre je: regex koja podržava nekoliko korisnih poboljšanja u odnosu na onu iz Python standardne biblioteke.
