Download: ProgPerl
Transkrypt
Download: ProgPerl
PROGRAMOWANIE Perl Archiwizacja i dostęp do plików PDF BIBLIOTEKARKA W tym miesiącu dowiemy się, jak umieszczać artykuły w prywatnym archiwum plików PDF oraz jak używać bazy danych, aby później móc z nich korzystać. MICHAEL SCHILLI C iekawy artykuł z lokalnej gazety czy też świetna analiza polityczna z New Yorkera umilą nam deszczowe popołudnia. Dlatego warto zachować je na takie okazje. Niestety, nie wszystko jest dostępne w sieci, ponieważ wielu wydawców nie chce publikować w Internecie. To źle, gdyż czasopisma zajmują dużo miejsca. Czy na pewno chcemy wynająć szopę lub zapełnić półki na książki segregatorami pełnymi wycinków? W końcu zależy nam tylko na jednym artykule; nikt nie czyta ponownie całych gazet po dwóch latach od ich ukazania się. Można jednak zeskanować ciekawe fragmenty i zapisać je na dysku w postaci plików PDF. Dzisiejszy skrypt perlowy, magsafe, ma zapewnić archiwiście kontrolę nad stale rosnącą kolekcją. Skanowanie i kompresowanie Dwie lub trzy strony można szybko zeskanować świetnym graficznym narzędziem xsane z projektu Sane [2]. Prawie każdy znany skaner jest obsługiwany przez zaplecze Sane. Zarówno skaner fotograficzny Epson, jak i skaner wbudowany w wielofunkcyjne urządzenie OfficeJet firmy HP świetnie sprawował się w Linuksie w naszym laboratorium perlowym. Po zeskanowaniu zapisujemy pojedyncze pliki w formacie PNG. Wybór 200 dpi ja- 86 NUMER 17 CZERWIEC 2005 ko rozdzielczości skanera powinien wystarczyć, aby tekst pozostał czytelny, a późniejszy ewentualny wydruk był możliwy. Narzędzie convert korzysta ze sztuczki opisanej w [3], łącząc wiele stron w jednym dokumencie PDF: convert -density 200 §§ -quality 95 \ -resize „1600x1600>” §§ *.png archive.pdf To polecenie łączy pliki *.png z bieżącego katalogu, ograniczając wysokość i szerokość do 1600 pikseli. Mniejsze obrazy są pozostawione bez modyfikacji dzięki znakowi >. Polecenie convert łączy pojedyncze strony, tworząc wielostronicowy plik PDF o rozdzielczości 200 dpi. Pliki PNG są kompresowane w formacie JPG w pliku PDF, zachowując 95% oryginalnej jakości. Do archiwum Po zeskanowaniu wszystkich jedenastu stron ze świetnego artykułu „Outsourcing Torture” Jane Mayer z New Yorkera i przekonwertowaniu ich na plik archive.pdf, za pomocą następującego wywołania skryptu magsafe dołączamy go do archiwum: magsafe -m „New Yorker” -a §§ „Jane Mayer” -t „Outsourcing Torture” WWW.LINUX-MAGAZINE.PL -i 2005/02/14 -p 106 -d §§ archive.pdf To polecenie tworzy rekord z tytułem publikacji (New Yorker), tytułem dokumentu (Out- Uwaga redakcji Ten artykuł przedstawia techniki związane z przechowywaniem i odczytem plików PDF. Zakłada się, że użytkownik posiada egzemplarz skanowanego czasopisma. Zakłada się także, że plik PDF jest tworzony do użytku własnego i nie będzie rozpowszechniany. Jednak prawa dotyczące skanowania materiałów objętych prawami autorskimi są skomplikowane i zależą od rozstrzygnięć w danym kraju. W niektórych systemach prawnych istnieje ograniczenie liczby artykułów, które można skopiować z jednego wydania (np. jeden artykuł na wydanie) lub na długość czasu, przez jaki artykuł może pozostawać w postaci archiwalnej. Przed zastosowaniem tych technik w wypadku materiałów chronionych prawem autorskim, należy sprawdzić, jakie regulacje prawne ich dotyczą. W Polsce i w większości krajów Europy dozwolona jest archiwizacja na użytek własny; do celów naukowych dozwolone jest u nas także powielanie artykułów z czasopism, niebędących własnością badacza. Te regulacje mogą się jednak zmieniać. My tylko pokazujemy kod w języku Perl. Perl sourcing Torture), wydaniem (2005/02/14) i stroną początkową (106). Dane są przechowywane w autentycznej bazie danych, obsługującej zapytania w języku SQL. W tej perlowej rubryce korzystali- $ magsafe [1] Nowy [2] New Yorker [3] Southwest London Inquirer Czasopismo [1]> Ponieważ już wcześniej wprowadziliśmy dwie publikacje, skrypt magsafe odnotował tytuły gazet i teraz wyświetla menu w postaci punktów. Aby dodać nowe czasopismo, naciskamy klawisz 1 i wprowadzamy nazwę publikacji. Czasopismo [1]> 1 Wprowadź nazwę czasopismaU []> Chiromancja na co dzień Dokument []> ... Rysunek 1: Skanowanie artykułu w programie xsane. śmy z mechanizmu bazy danych SQLite, gdyż jest ona niezwykle łatwa do zainstalowania. W sekcji „Installation” można się przekonać, że potrzebnych jest zaledwie kilka modułów z sieci CPAN, a skrypt załatwi resztę. Nie trzeba uruchamiać demona, definiować bazy danych czy tabel – znowu skrypt robi to wszystko sam. Skrypt nie kopiuje dokumentu PDF archive.pdf do bazy danych, lecz do katalogu, gdzie dokumenty przechowywane są w plikach o nazwach numerycznych (000001, 000002, ...). Wprowadzenie tekstu z New Yorkera do świeżej bazy spowoduje utworzenie dokumentu o nazwie „000001”, z danymi pliku PDF. Naszym drugim rekordem będzie artykuł z lokalnej gazety, dotyczący burdy w londyńskim pubie. magsafe -m §§ „Southwest London Inquirer” -t „Pint Glasses Flying Low” -i 2005/02 -p 4 -d §§ archive.pdf Jak widać, nie trzeba podawać nazwiska autora; zresztą krótkie teksty w gazetach często nie są podpisane nazwiskiem, tylko inicjałami. Po wywołaniu skryptu magsafe bez parametrów pojawią się interaktywne pytania o szczegóły. Program magsafe kopiuje dokument PDF określony przez opcję -d (lub wprowadzony interaktywnie) do ustalonego z góry katalogu, przypisując numery seryjne poszczególnym dokumentom (000001, 000002 i tak dalej) oraz wprowadzając ścieżki do tych plików z bazy danych. Igła w stogu siana Oczywiście, baza danych daje możliwość przeszukiwania w dowolny sposób. W wypadku naszej gazetowej bazy danych, którą przechowujemy w pliku scanned_docs.dat, jest to bardzo łatwe przy użyciu narzędzia wiersza poleceń sqlite3 i paru instrukcji starego, dobrego języka SQL: $ sqlite3 scanned_docs.dat sqlite> SELECT * from doc where title like '%Pint%' 2|Pint Glasses Flying Low§§ ||2|4|2005/02 CTRL-D $ Można narzekać, że to nieco niewygodne. Słusznie. Dlatego właśnie magsafe ma też uproszczony język zapytań. Jeśli użyjemy parametru -s, musimy podać wyszukiwany ciąg w formacie: „pole:wzorzec pole:§§ wzorzec ...” Następujący wiersz oznacza wyszukanie artykułów zawierających w tytułach wyraz Pint: $ magsafe -s title:Pint „Pint Glasses Flying Low”, §§ WWW.LINUX-MAGAZINE.PL PROGRAMOWANIE Anonim, Southwest London §§ Inquirer, 2005/02, 4, /DATA/DOCS/000002 Sam magsafe generuje zapytanie SQL na podstawie wprowadzonych danych, otaczając wyszukiwany ciąg znakami procenta. Załóżmy, że szukamy artykułów opublikowanych w roku 2005, to znaczy z wartością „2005” w polu issue. W takim wypadku wpisalibyśmy: magsafe -s issue:2005 Jeśli to zapytanie zwróci za dużo trafień, można dodatkowo ograniczyć zapytanie do artykułów z „Southwest London Inquirer”, używając parametru mag:: magsafe -s „issue:2005 §§ mag:Southwest” Abstrakcyjna baza danych Już parę raz w tym dziale korzystałem z abstrakcyjnej bazy danych Class::DBI, stosowanej także w skrypcie magsafe. Dziś będzie jeszcze prościej. Moduł Class::DBI::Loader upraszcza definicje klas modułu Class::DBI, analizując układ tabeli bazy danych i generując klasy abstrakcyjne oraz ich relacje przez odwołanie do nich. Listing programu magsafe ukazuje, w jaki sposób jest to zaimplementowane. Moduł Getopt::Std przetwarza opcje wiersza poleceń zrozumiałe dla skryptu magsafe. W wierszu 29 poszukujemy opcji -a, -m, -t i tak dalej. Dwukropki w ciągu formatu wymuszają występowanie parametru za każdą tak oznaczoną opcją. Funkcja getopts przechowuje wartości w tablicy asocjacyjnej %o, przetwarzanej później. W wierszu 33 sprawdzamy, czy istnieje katalog dokumentów (może być pusty) i czy można w nim zapisywać pliki. Jeśli nie, katalog należy utworzyć przed uruchomieniem programu. Funkcja db_init () wywoływana w wierszu 36 zapewnia, że użytkownicy nie będą musieli troszczyć się sami o szczegóły funkcjonowania bazy danych. Jeśli baza danych nie istnieje, w funkcji db_init () w wierszu 147 za pomocą paru instrukcji SQL tworzy nową bazę danych z dwoma tabelami. Na Rysunku 2 widać schemat. Tabela doc zawiera wiersz dla każdego zapisywanego dokumentu. Wiersz posiada tytuł i autora artykułu, wydanie i stronę, a także nazwę publikacji, z której pochodzi artykuł. NUMER 17 CZERWIEC 2005 87 PROGRAMOWANIE Perl Ponieważ większość ludzi nie czyta zbyt wielu periodyków, lecz czyta je regularnie co miesiąc, przechowywanie pełnego tytułu publikacji w każdym wierszu świadczyłoby o złym projekcie bazy danych. Zamiast tego tabela doc ma pole mag z numerycznym identyfikatorem, który wskazuje wiersz w tabeli mag, zawierającej identyfikator wraz z pełną nazwą publikacji. Definicje tabeli, następujące od wiersza 147 w skrypcie magsafe, są zgodne ze standardem SQL, łącznie z wierszem Pierwsze dwie kolumny w obu tabelach to identyfikatory numeryczne, oznaczone jako primary key (klucz podstawowy). Konstruktor klasy Class::DBI::Loader wywołany w wierszu 40 potrzebuje ich do przydzielania unikatowych identyfikatorów obiektom tworzącym wiersze w tabeli. Nowo utworzone wiersze mają automatycznie przydzielane nowe identyfikatory, większe o jeden od ostatnich użytych identyfikatorów. Następujący wiersz: namespace => „Scanned::DB” mag INT REFERENCES mag, Rysunek 2: Układ bazy danych SQLite. w tabeli doc, który wygląda może nieco niezwykle. W taki sposób wyrażamy, że kolumna mag wskazuje na kolumnę mag i ustalamy relację między identyfikatorem publikacji a tytułem. w konstruktorze klasy ładowania bazy danych zapewnia, że abstrakcyjne klasy tabeli będą widoczne w języku Perl w obszarze nazw Scanned::DB. Po wywołaniu metody Class::DBI::Loader->new () metoda find_class () pobiera obiekty Listing 1: „magsafe” 001 002 003 004 005 006 007 008 009 010 011 012 013 014 015 016 017 018 019 020 021 022 023 024 025 026 027 028 029 030 031 032 033 88 #!/usr/bin/perl -w ############################# # magsafe - Archiwum # artykułów z czasopism # Mike Schilli, 2005 # ([email protected]) ############################# use strict; use use use use use DBI; Class::DBI::Loader; Sysadm::Install qw(:all); Getopt::Std; Text::Iconv; my $DB_NAME = "/DATA/scanned_docs.dat"; my $DSN = "dbi:SQLite:$DB_NAME"; my $UTF8_TERM = 1; my $cv = Text::Iconv->new("Latin2", "utf8"); $cv->raise_error(1); my $DOC_DIR = "/DATA/DOCS"; getopts("a:m:t:i:p:d:s:", \my %o); die "$DOC_DIR nie gotowy" if !-d $DOC_DIR NUMER 17 CZERWIEC 2005 034 035 036 037 038 039 040 041 042 043 044 045 046 047 048 049 050 051 052 053 054 055 056 057 058 059 060 061 062 063 064 065 066 or !-w $DOC_DIR; db_init($DSN) unless -e $DB_NAME; my $loader = Class::DBI::Loader->new( dsn => $DSN, namespace => "Scanned::DB", additional_classes => qw( Class::DBI::AbstractSearch ), relationships => 1, ); my $docdb = $loader->find_class("doc"); my $magdb = $loader->find_class("mag"); my @objs = (); if (!exists $o{s}) { my $mag = mag_pick($magdb, $o{m}); my $doc = $o{d} || ask "Dokument", ""; my $author = $o{a} || ""; my $title = $o{t} || ask "Tytuł", ""; my $page = $o{p} || ask "Strona", ""; my $issue = $o{i} WWW.LINUX-MAGAZINE.PL 067 || ask "Wydanie", ""; 068 069 my $id = $mag->add_to_docs( 070 { 071 map { 072 $UTF8_TERM 073 ? $_ 074 : $cv->convert($_) 075 } 076 title => $title, 077 page => $page, 078 issue => $issue, 079 author => $author 080 } 081 ); 082 083 cp $doc, docpath($id); 084 exit 0; 085 } 086 087 my %search = (); 088 089 for (split ' ', $o{s}) { 090 091 my ($field, $expr) = 092 split /:/, $_; 093 094 if ($field eq "mag") { 095 my @mags = 096 $magdb->search_like( 097 name => "%$expr%"); 098 099 $search{$field} = Perl reprezentujące tabele, jak widać w wierszach 50 i 52, podając nazwy tabel jako argumenty. Obiekt $docdb typu Scanned::DB::Doc wskazuje na tabelę dokumentów doc, a obiekt $magdb (Scanned::DB::Mag) na tabelę publikacji mag. Aby obiekty mogły wykonywać zapytania standardowe modułu Class::DBI, a także obsługiwać bardziej skomplikowane warunki WHERE, stosujemy parametr additional_classes w wierszu 43. Żąda on pakietu Class::DBI::AbstractSearch. Flaga relationships w wierszu 46 nakazuje klasie Class::DBI::Loader analizować relacje miedzy tabelami doc i mag oraz łączyć je obie. Dzięki warunkowi REFERENCES w kodzie SQL kolumna mag w tabeli doc jest rozpoznawana jako klucz zewnętrzny służący do wykonywania operacji JOIN z tabelą mag. Obiektowa abstrakcja bazy danych może więc za- pewnić metody służące do nawigacji między dwiema tabelami. Sterowanie z wiersza poleceń W wierszu 56 skrypt przetwarza parametry wiersza poleceń. Jeśli opcja -s nie jest ustawiona, użytkownik nie szuka istniejącego wpisu w bazie danych, lecz wprowadza nowy wiersz. Wiersze od 59 do 66 przyjmują wartości z różnych opcji wiersza poleceń takie jak tytuł, autor, dokument, publikacja, strona i wydanie. Jeśli co najmniej jedna opcja nie jest ustawiona, funkcja ask () (wstawiana przez moduł Sysadm::Install) interaktywnie generuje pytanie do użytkownika, dotyczące brakujących wartości. Pole autora jest opcjonalne i nie pojawia się prośba o wpisywanie go. PROGRAMOWANIE Wybór publikacji jest nieco bardziej skomplikowany. Opiera się na funkcji mag_pick zdefiniowanej w wierszu 169 i następnych. Metoda retrieve_all () obiektu tabeli bazy danych $magsdb odczytuje wszystkie istniejące wiersze w tabeli mag. Zwrócone obiekty danych zapewniają metody udostępniające poszczególne pola w rekordach: na przykład metoda $obj->name () zwraca nazwę publikacji, zapisaną w kolumnie name tabeli mag. Jeśli zmienna $picked nie jest ustawiona, to znaczy opcja wiersza poleceń dla nazwy publikacji jest pusta, w wierszu 179 używa się funkcji pick () (także z modułu Sysadm::Install). Tworzy ona menu z nazwami czasopism. Jeśli użytkownik wybierze pierwszy element, Nowy, w wierszu 181 wybór jest unieważniany, a wiersz 186 umożliwia użytkownikowi wpisanie nazwy publikacji, która wyświetli się na liście wyboru następnym razem. Metoda Listing 1: „magsafe” 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 [ map { $_->id() } @mags ]; } else { $search{$field} = "%$expr%"; } } @objs = $docdb->search_where( \%search, { cmp => "like" } ); if (@objs) { print join(", ", '"' . $_->title() . '"', $_->author() || "Anonim", $_->mag()->name(), $_->issue(), $_->page(), docpath($_->docid())), "\n" for @objs; } else { print STDERR "Brak wpisów\n"; } ############################# sub docpath { ############################# my ($id) = @_; return sprintf "%s/%06d", 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 $DOC_DIR, $id; } ############################# sub db_init { ############################# my ($dsn) = @_; my $dbh = DBI->connect($dsn, "", ""); $dbh->do( q{ CREATE TABLE doc ( docid INTEGER PRIMARY KEY, title VARCHAR(255), author VARCHAR(255), mag INT REFERENCES mag, page INT, issue VARCHAR(32) ); } ); $dbh->do( q{ CREATE TABLE mag ( magid INTEGER PRIMARY KEY, name VARCHAR(255) ); } ); } WWW.LINUX-MAGAZINE.PL 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 ############################# sub mag_pick { ############################# my ($magsdb, $picked) = @_; my @mags = map { $_->name() } $magsdb->retrieve_all(); if (@mags and !$picked) { $picked = pick "Czasopismo", [ "Nowy", @mags ], 1; undef $picked if $picked eq "Nowy"; } if (!$picked) { $picked = ask "Wprowadź nazwę czasopisma", ""; } $picked = $UTF8_TERM ? $picked : $cv->convert($picked); my $mag = $magsdb->find_or_create( { name => $picked }); return $mag; } NUMER 17 CZERWIEC 2005 89 PROGRAMOWANIE Perl find_or_create () tworzy nowy wpis w tabeli mag lub znajduje istniejący wpis czasopisma. Zmienna $mag w wierszu 57 reprezentuje nowo utworzone lub istniejące czasopismo. Ponieważ klasa Class::DBI::Loader spisała się dobrze już poprzednio i przeanalizowała relacje między tabelami doc i mag, co nakazywała flaga relationships, w wierszu 52 można po prostu wywołać metodę $mag->add_to_docs (). Doda ona artykuł do tabeli doc i zapewni, że kolumna mag będzie wskazywać publikację w tabeli mag. Metoda add_to_docs () obiektu czasopisma nie jest jawnie zdefiniowana w skrypcie magsafe. Jest ona automatycznie generowana przez warstwę abstrakcji bazy danych DBI::Class po ustaleniu relacji między tabelami. Aby skopiować bieżący dokument PDF do katalogu dokumentów, skrypt magsafe wywołuje funkcję cp z modułu Sysadm::Install w wierszu 83. Funkcja docpath (), zdefiniowana od wiersza 129, zwraca pełną przyszłą ścieżkę pliku. W tym celu po prostu konwertuje przekazany do niej identyfikator na sześciocyfrową liczbę całkowitą, dopełnioną zerami, a następnie dołącza ją do ścieżki katalogu dokumentów. Prościej niż SQL W wypadku żądania wyszukiwania wiersz 89 iteruje po parach kolumna:wzorzec, podanych przez opcję -s i rozdzielonych spacjami. Wiersz 92 rozdziela nazwę kolumny od klucza wyszukiwania. Jeśli nazwa kolumny to mag, w wierszu 96 po prostu jest wyszukiwane pasujące czasopismo, przez umieszczenie klucza wyszukiwania w znakach procenta i wywołanie funkcji search_like () w odniesieniu do tabeli mag. Może ona nie zwrócić żadnych obiektów czasopism, ale także jeden lub więcej w tablicy @mags. Odpowiednia metoda id () znajduje identyfikatory czasopism, dzięki czemu w wierszu 99 może być zapisana krótka: „mag” => [$id1, $id2, ...] w tablicy asocjacyjnej %search. Zmienne $id1, $id2 i tak dalej to identyfikatory numeryczne czasopism pasujące do żądania wyszukiwania, a wpis do tablicy asocjacyjnej przypisany kluczowi „mag” wskazuje na tablicę zawierającą te identyfikatory. Z drugiej strony, jeśli użytkownik szuka innej kolumny niż mag, realizowane jest odgałęzienie else w wierszu 103, a klucz wyszukiwania jest otaczany znakami procenta 90 NUMER 17 CZERWIEC 2005 i przypisywany kluczowi nazwy tabeli w tablicy asocjacyjnej %search. Zawartość tablicy asocjacyjnej %search jest przetwarzana przez metodę search_where (), wywoływaną w wierszu 108. Zwraca ona wiersze pasujące do wszystkich warunków określonych w tablicy. Jeśli parametr porównania cmp ma dodatkowo wartość „like” w dodatkowej tablicy asocjacyjnej opcji, metoda search_where () nie poszukuje dokładnych trafień, lecz wzorców podanych ze znakami % , zgodnie ze standardem SQL. Polecenie print w wierszu 113 jest wywoływane dla każdego znalezionego obiektu przez warunek for @obs. Łączy ono znalezione wpisy kolumny w tabeli i tworzy sformatowaną postać wyjścia. Ścieżka do dokumentów PDF jest odtwarzana metodą docpath(), wspomnianą już wyżej. Jeśli wyszukiwanie nie zwraca żadnych trafień, wiersz 124 na urządzeniu STDERR generuje tekst Brak wpisów. Niestandardowe znaki Trzeba pamiętać, że baza SQLite3 wymaga kodowania ciągów jako UTF-8. Nie można zapisywać polskich znaków w formacie ISO-8859-2. Ustawienia lokalnego terminala określają, czy dane wprowadzane są w kodowaniu UTF-8, czy też ISO 8859-2. W wielu nowszych dystrybucjach linuksowych są terminale UTF-8, a w starszych ustawiało się zwykle ISO 8859-2. Należy sprawdzić zmienną środowiskową LANG: jeśli ma wartość pl_PL.UTF-8, to znaczy, że terminal ma zestaw znaków UTF-8. Skrypt można przystosować do środowiska: jeśli zmienna $UTF8_TERM w wierszu 16 ma poprawną wartość, skrypt będzie interpretować dane wprowadzane przez użytkownika jako zakodowane w standardzie UTF-8 i nie wykona konwersji. Jeśli zmienna $UTF8_TERM ma wartość 0, skrypt magsafe uzna, że dane użytkownika mają zestaw znaków ISO 8859-2 i przekonwertuje wszystko na UTF-8 przed umieszczeniem ich w bazie danych. W razie potrzeby konwersji skrypt magsafe skorzysta z modułu Iconv z sieci CPAN. W wierszu 23 tworzony jest obiekt Text::Iconv w celu konwersji z ISO-8859-2 na UTF-8. Dodatkowo jest wywoływana funkcja raise_error () z wartością 1 w celu wywołania wyjątku w razie błędu. Metoda convert () konwertuje przekazane ciągi z jednego rodzaju kodowania na inny. Osoby mające zainstalowane interpreter perl 5.8.x lub nowszy mogłyby użyć też modułu Encode. WWW.LINUX-MAGAZINE.PL Instalacja Skrypt wymaga modułów DBI, Class::DBI, Class::DBI::SQLite, Class::DBI::AbstractSearch i DBD::SQLite do abstrakcji bazy. Są one dostępne w sieci CPAN. Poza tym wymagane są moduły Text::Iconv i Sysadm::Install. Można je zainstalować w prosty sposób z poziomu powłoki CPAN. Jeśli wolimy ręcznie używać klienta wiersza poleceń sqlite3 do obsługi bazy danych SQL, możemy pobrać kod źródłowy w formacie tar z [4], skompilować go i zainstalować. Wcześniejsze wersje (SQLite 1 lub 2) nie będą działać, gdyż moduł DBD::SQLite opiera się na programie SQLite 3.x, niezgodnym z bazami utworzonymi w innych wersjach. Narzędzie wiersza poleceń trzeciej generacji nosi nazwę sqlite3, w przeciwieństwie do narzędzi z wersji poprzednich, które nazywały się po prostu sqlite. Uwaga: jeśli używamy baz danych SQLite do innych celów z wcześniejszymi wersjami modułu DBD::SQLite i nadal chcemy z nich korzystać, musimy je przekonwertować na nowy format SQLite przed modernizacją. sqlite OLD.DB .dump | §§ sqlite3 NEW.DB Po zainstalowaniu najnowszej wersji modułu DBD::SQLite nie będzie można odczytać baz danych utworzonych we wcześniejszych wersjach. Zmienna $DOC_DIR definiuje katalog dokumentów w wierszu 27 skryptu magsafe. Natomiast zmienna $DB_NAME w wierszu 16 ustawia nazwę pliku bazy danych SQLite. Jej katalog powinien istnieć przed uruchomieniem programu i należy mieć prawo zapisu do niego. Reszta jest automatyczna: SQLite automatycznie tworzy plik bazy danych zdefiniowany przez $DB_NAME i inicjuje tabele. A teraz fani wycinków mogą zeskanować ważne teksty z przeczytanych pism i wyrzucić je na makulaturę. Ile miejsca można w ten sposób zaoszczędzić! ■ INFO [1] Listing do tego artykułu: http://www.linux-magazine.com/Magazine/Downloads/55/Perl [2] http://www.sane-project.org [3] PDF Hacks, Sid Steward, O'Reilly 2004 [4] Strona SQLite, http://www.sqlite.org