|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Menu
Distributions (131)
Software (10844)
|
Perl (42) - Argumenty příkazového řádkuV dnešním díle se naučíme zpracovávat argumenty příkazového řádku.
Perl by nebyl plnohodnotným jazykem kdyby neuměl obsloužit argumenty programů. Toto téma jsme již naťukli v souvislosti se soubory, kdy jsme zmiňovali ovladač <> (resp. <ARGV> se stejným významem). Pomocí něj jsme byly schopni číst soubory, které byly předány jako argument na příkazovém řádku. Ovladač <>Ovladač <> funguje tak, že si Perl nejprve ověří, zda existují soubory se jmény uvedenými jako argumenty. Pokud ano, pak tyto soubory otevře, použije jako zdroj dat a zpřístupní ho ovladačem <>. Tato metoda je ale vhodná pouze pro úzkou množinu programů. Přesněji řečeno pro ty, které vyžadují jako argument soubor, ze kterého se bude číst. Jistým zjednodušením je i to, že všechny soubory se slijí do jednoho. Pro určité úlohy je tedy ovladač <> vhodný, ale pro jiné nikoliv. Co kdybychom pouze chtěli zjistit velikost předaného souboru? A co kdyby vůbec nebyl předáván název souboru, ale libovolný řetězec? Na to potřebujeme obecnější metodu pro práci s argumenty. @ARGVPerl nabízí pro práci s argumenty příkazového řádku na nejnižsí úrovni speciální pole @ARGV. Veškeré parametry předané programu jsou v tomto poli automaticky uloženy. Další speciální proměnnou s podobným významem, tentokrát skalární, je $0. Ta obsahuje jméno programu. S regulárnímy výrazy nemá nic společného, přestože se tak na první pohled může zdát. Proměnné pro zapamatování však začínají od 1. Ukažme si, jak to vypadá v praxi. Mějme program ll, kterému předáme jako argumenty jména souborů. U těchto souborů vytiskne příkaz ll informace o i-uzlu, podobně jako unixové ls -l.
ll ghost.png db.sql data install.py
Pokud zavoláme program tímto způsobem, bude obsah proměnných $0 a @ARGV následující:
PříkladNapíšeme si výše zmíněný program ll. Ten bude přijímat argumenty příkazového řádku. ll bude vypisovat, jakého typu je soubor (adresář, roura, atd.), práva, počet odkazů, vlastníka (uživatel i skupina), velikost, datum, čas a jméno souboru. ll tak bude napodobovat ls -l, jen nebude vyladěn do takových detailů. Nejprve si udělejme nějakou koncepci. Postup bude následující.
Zde máme hlavní cyklus programu, který v každé iteraci vyšetří 1 předaný existující soubor.
#!/usr/bin/perl V každém cyklu tak zpracujeme 1 argument, který bude uložen vždy v proměnné $_. Teď budeme postupně zjišťovat informace o i-uzlech. Za prvé zde je typ souboru. To vyřešíme podprogramem zjisti_typ_souboru. Obdobně získáme i řetězec práv. V dalším sloupci máme počet odkazů na soubor. Ten není problém zjistit, protože tuto informaci máme uloženou na 4. pozici v seznamu, který vrací funkce stat. Jméno vlastníka a skupiny dostaneme voláním getpwuid resp. getgrgid. Předposledním sloupcem je velikost, kterou získáme taktéž pomocí funkce stat. A nakonec potřebujeme datum a čas. My máme pouze počet sekund od 1.1.1970. Proto musíme opět použít podprogram. Nyní máme alespoň teoreticky veškeré potřebné údaje. Vytiskneme je funkcí printf. Oproti příkazu ls -l použijeme pro každou hodnotu pevnou šířku sloupce. Hlavní cyklus bude na základě těchto údajů vypadat takto.
for (@ARGV){ Zbývá nám dopsat jednotlivé podprogramy. Začneme určením typu souboru. K tomu si připomeňme speciální operátory pro soubory. Budeme rozeznávat obyčejné soubory, adresáře, symbolické odkazy, roury, sockety, blokové a znakové soubory. V tomto podprogramu nám postačí jednoduchý switch.
sub ziskej_typ_souboru {
Další na řadě máme řetězec práv. To bude vůbec nejsložitější část programu. Ohled musíme brát i na sticky bit, set UID a set GID. A co k tomu vlastně máme k dispozici? Prakticky jen příkaz stat, pomocí kterého lze zjistit desítkový formát přístupových práv. Vše se tedy bude odehrávat v podprogramu ziskej_prava, který obdrží jako argument desítkový zápis práv.
sub ziskej_prava { Nejdříve musíme získat osmičkový zápis přístupových práv, se kterým se bude lépe pracovat.
my $oct_prava = sprintf "%o", $dec_prava & 07777;
Dále si celý problém rozdělíme do 3 kroků. Bude to spíše manuální práce než vymýšlení algoritmů. Zde je postup.
Pokud je sticky bit, set UID nebo set GID nastaven, je zároveň hodnota $dec_prava větší než 777 a je čtyřmístná. Takže pokud lze odečíst příslušné hodnoty, uděláme to a zároveň nastavíme proměnné $sbit, $suid a $sgid. Připomeňme si, že pro set UID odečítáme 4000, pro set GID 2000 a pro sticky bit 1000.
if (length $oct_prava == 4){ První a nejjednodušší krok máme úspěšně za sebou, zbývají ještě 2. Protože nyní víme, že je hodnota $dec_prava vždy trojmístná, můžeme jednotlivé cifry rozdělit.
my($vlastnik, $skupina, $ostatni) = split "", $oct_prava;
Od každé z proměnných $vlastnik, $skupina a $ostatni opět budeme postupně odečítat hodnoty (právo pro čtení 4, pro zápis 2, pro spouštění 1) a zároveň přidávat práva (byla-li příslušná hodnota odečtena). V případě absence práva zapíšeme znak -.
for my $us ($vlastnik, $skupina, $ostatni){ V proměnné $retezec nyní máme řetězec práv a musíme do něj zahrnout $sbit, $suid a $sgid. Existuje-li $suid, nahradíme 3. znak řetězce za s (pokud tam už je x) nebo za S (pokud tam není). Použijeme funkci substr. Její 4. parametr - řetězec, kterým se bude (v našem případě 3. znak) nahrazovat tedy bude právě s nebo S.
if ($suid == 1){ Jestliže je právě na 3. pozici znak x (což zjistíme opět příkazem substr), 4. parametrem bude s. Jinými slovy - prostor pro podmínkový operátor.
if ($suid == 1){ To samé uděláme i s set GID a sticky bit.
if ($sgid == 1){ A na závěr vrátíme výsledný řetězec.
return $retezec;
Posledním podprogramem zjistíme datum a čas. V něm získáme všechny potřebné údaje od funkce localtime. Stačí je pouze vhodně poskládat a vrátit.
sub zjisti_cas { To je celé. Oproti ls -l se sice ll v mnoha rysech významně liší (stačí porovnat výstupy po zadání adresáře), ale přesto nám posloužil jako názorná ukázka. $ ./ll TEST -rws--Sr-T 1 jv users 0 2005-07-07 13:56 TEST $ ls -l TEST -rws--Sr-T 1 jv users 0 2005-08-07 13:56 TEST $
|
Search Software
Search Google
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
©Pavel Kysilka - 2003-2024 | maillinuxsoft.cz | Design: www.megadesign.cz |