Poslední díl týkající se získáváním a zpracováním parametrů příkazového řádku se podrobně zabývá prací s dlouhými přepínači. Zmíníme se i o tom, jak zpracovávat dlouhé a krátké přepínače najednou.
11.10.2006 06:00 | Jiří Václavík | přečteno 21719×
Celý mechanizmus dlouhých přepínačů, který dnes přiblížíme, zajišťuje modul Getopt::Long. Již jsme si představili modul Getopt::Regex, který zpracovávat dlouhé přepínače umí. Nicméně oba tyto moduly se hodí každý na něco trochu jiného a tak se výhodně doplňují.
Dlouhé přepínače budeme rozlišovat do kategorií zejména podle typu argumentu.
Modul Getopt::Long má tu vlastnost, že dokáže zpracovat i volby, které jsou uvedeny za jinými argumenty (jména souborů...). To znamená, že budou všechny volby nalezeny i v případech jako je tento.
$ ./program --verbose soubor1 soubor2 --extract
Avšak existuje znaménko dvojité pomlčky. Pomocí ní lze dát modulu Getopt::Long na vědomí, že dále už nemá prohledávat. V dalším volání programu ./program, který používá Getopt::Long, se zpracuje už jen volba --verbose.
$ ./program --verbose -- soubor1 soubor2 --extract
Getopt::Long podporuje i zápis přepínače s jednou pomlčkou. Při volání tak lze psát --verbose i -verbose.
Další vlastností modulu je, že funkce GetOptions implicitně nerozlišuje velikost písmen. Program lze volat s volbou --extract a účinek je stejný jako kdybychom předávali --ExtrACT. Implicitní chování je možné změnit uvedeným způsobem.
Getopt::Long::Configure("no_ignore_case");
Getopt::Long poskytuje již zmíněnou funkci GetOptions, jejíž syntaxe vypadá obecně takto. Do proměnných uvedených jako hodnoty prvků se ukládají data získaná na základě příslušných přepínačů.
GetOptions("prepinac1" => \$promenna1, "prepinac2" => \$promenna2, ...);
Nejjednodušším případem dlouhých přepínačů je přepínač bez hodnoty. Napíšeme kód, který bude přijímat volby --get a --verbose.
use Getopt::Long;
GetOptions(
"verbose" => \$verbose,
"get" => \$get
);
print "verbose = $verbose\n";
print "get = $get\n";
Do proměnných předaných funkci GetOptions se bude ukládat pravdivá nebo nepravdivá hodnota podle toho, zda byl ten který přepínač zadán.
$ ./getopt.pl --verbose verbose = 1 get = $
Inkrementační volby jsou cestou, jak rozlišit, kolikkrát byla zadána tatáž volba.
Přidáním znaménka + (ve zdrojovém kódu podtrženo) na konec jména přepínače docílíme toho, že se hodnota v dané proměnné nenastaví na pravdivou hodnotu, ale inkrementuje se. A inkrementuje se tolikrát, kolikrát byla zadána.
use Getopt::Long;
$verbose = 0;
GetOptions("verbose+" => \$verbose);
print "Ukecanost = $verbose\n";
Zadáme-li tomuto skriptu volbu --verbose, funkce GetOptions přenastaví hodnotu proměnné $verbose na 1. Pokud zadáme --verbose --verbose, $verbose se zvětší na hodnotu 2, apod.
Představme si, že chceme nabídnout 2 volby pro 1 proměnnou - jednu pro výslovné true a druhou pro výslovné false. Tedy například --list a --no-list (resp. --nolist). Je zbytečné uvádět v GetOptions 2 volby, protože stačí jedna. Jestliže za volbu připíšeme vykřičník (opět podtržen), automaticky vzniká další volba s předponou no- (resp. no).
use Getopt::Long;
GetOptions("list!" => \$list);
print "list = $list\n";
Uvedením --list se proměnná $list nastaví na 1, naopak --no-list nastavuje 0. Obsahy příslušných proměnných jsou zřejmé z výstupu programu.
$ ./getopt.pl list = $ ./getopt.pl --list list = 1 $ ./getopt.pl --nolist list = 0 $
Pro to, aby byly zpracovávány i hodnoty voleb, je nutné za volbu v příkazu GetOptions uvést znak = (má-li být hodnota volby povinná) nebo : (má-li být nepovinná) a za ním datový typ. Ten nabývá těchto hodnot.
Hodnota | Význam |
s | řetězec |
f | desetinné číslo |
i | klasické celé číslo |
o | celé číslo; je zde navíc podpora dvojkové (0b), osmičkové (0), šestnáctkové (0x) soustavy a znamének |
Uveďme si krátký kód, vyžadující celočíselnou hodnotu přepínače, pokud je tento přepínač uveden.
use Getopt::Long;
GetOptions("size=i" => \$size);
print "size = $size\n";
Jestliže volbu nezadáme, nebude program protestovat. Varování ale vypíše tehdy, pokud zadáme volbu bez hodnoty.
$ ./getopt.pl --size=11 size = 11 $ ./getopt.pl --size Option size requires an argument size = $ ./getopt.pl size = $
Je-li použit znak :, lze za něj napsat i hodnotu, která bude dané proměnné přiřazena v případě, že bude na příkazovém řádku zadán poze přepínač bez hodnoty. Přepínači --size nastavíme jako implicitní hodnotu 12.
use Getopt::Long;
GetOptions("size:12" => \$size);
print "size = $size\n";
Pokud v GetOptions zaměníme odkaz na skalár za odkaz na pole, bude vloženo tolik hodnot, kolik jich bylo zadáno.
use Getopt::Long;
GetOptions("file=s" => \@file);
print "file = @file\n";
Při zadávání více hodnot je nutné volbu opakovat tolikrát, kolik hodnot bude.
$ ./getopt.pl --file=create.sql --file=insert.sql file = create.sql insert.sql $
Funkci GetOptions lze předat dokonce i hash. Poté vyžaduje páry hodnot.
use Getopt::Long;
GetOptions("www=s" => \%www);
print "www = ";
print $_."=".$www{"$_"}." " for keys %www;
print "\n";
V takovém případě se volá program tímto způsobem.
$ ./getopt.pl -www www.linuxsoft.cz="Linux Software" --www www.google.com=Google www = www.google.com=Google www.linuxsoft.cz=Linux Software $
Podobně jako u jednoznakových přepínačů lze určit hash, do kterého se mají volby souhrnně ukládat. Formát takového hashe je pak $hash{"volba"} = hodnota.
Potom se ale poněkud mění fungování funkce GetOptions. Jako první parametr je nutno zadat odkaz na hash a dalšími parametry jsou jednotlivé volby.
use Getopt::Long;
GetOptions("\%volby, "height=f", "width=f", "length=f");
print $_."=".$volby{$_}."\n" for keys %volby;
GetOptions umožňuje výskyt synonymních voleb. To znamená, že lze nastavit 1 proměnnou pro více voleb. Takové volby pak mají totožný význam.
K tomu je třeba vepsat do GetOptions obě možnosti a oddělit je znakem |.
use Getopt::Long;
GetOptions("paste|insert|ins=s" => \$insert);
print "insert = $insert\n";
Nyní bude proměnná $insert nastavena ve všech těchto případech volání.
$ ./getopt.pl --insert=zvuk.ogg $ ./getopt.pl --paste=zvuk.ogg $ ./getopt.pl --ins=zvuk.ogg
Stejně jako odkaz na proměnnou je možné předávat odkaz na podprogram. V takovém případě se žádná proměnná nenastavuje, ale zato se v případě uvedení přepínače provede daný podprogram.
use Getopt::Long;
GetOptions("pozdrav" => sub {print "Ahoj!\n";});
Getopt::Long umožňuje zpracovávání dlouhých i krátkých přepínačů najednou. A to dokonce tak, aby bylo možné krátké volby seskupovat.
Slouží k tomu funkce Configure, která se stará o nastaveví chování modulu. Pokud jí jako parametr předáme hodnotu bundling (svazkování), bude brát přepínače s jednou pomlčkou vždy jako jednoznakové a se 2 pomlčkami jako dlouhé.
use Getopt::Long qw(Configure GetOptions);
Configure("handling");
GetOptions("decode" => \$decode, "x" => \$x, "y" => \$y, "z" => \$z);
print "x: $x\n";
print "y: $y\n";
print "z: $z\n";
print "decode: $decode\n";
Nyní se budou zadáním voleb -xyz --decode hledat přepínače -x, -y, -z a --decode. Pokud bude ale zadáno -xyz -decode budou považovány všechny všechny volby za jednoznakové: -x, -y, -z, -d, -e, -c, -o, -d a -e. To ve většině případů nemáme v úmyslu. Proto existuje pro funkci Configure ještě hodnota handling_override, která umí taková zadání rozpoznat. Potom bude fungovat i zápis -xyz -decode podle očekávání.
Jako základ o Getopt::Long by měl tento díl seriálu stačit. Pokud vás však informace v něm stále neuspokojily, pak můžete nahlédnout do dokumentace.