De verwerking van commandoregelargumenten is een basistaak voor Perl-programma's. Historisch gezien heeft Perl de variabele @ARGV geleverd voor toegang tot de argumenten die aan het script zijn doorgegeven. Het probleem is dat complexe scenario's vlaggen en sleutel-waarde parameters kunnen bevatten, wat een handmatige parsing van de array @ARGV vereist. Met een verkeerde aanpak kunnen parameters verkeerd worden verwerkt, verplichte waarden worden overgeslagen of extra waarden worden verwerkt, wat leidt tot fouten in de logica van het programma.
De oplossing is om een systematische verwerking te gebruiken: iteratie door @ARGV, inhoudsanalyse, verwerking van sleutels en hun waarden.
Voorbeeldcode:
my %args; while (my $arg = shift @ARGV) { if ($arg =~ /^--(\w+)=?(.*)/) { my ($key, $val) = ($1, $2); if ($val eq '' && @ARGV) { $val = shift @ARGV; # volgende waarde } $args{$key} = $val eq '' ? 1 : $val; } else { push @{$args{'_free'}}, $arg; } } print "Got foo: $args{foo} " if exists $args{foo};
Belangrijke kenmerken:
Wat gebeurt er als een argument wordt doorgegeven als '--flag value' in plaats van '--flag=value'?
Als je alleen rekening houdt met de splitsing via '=', zal de waarde een lege string zijn, en het volgende element van de array zal worden genegeerd als een zelfstandig argument. De oplossing is om beide varianten in de parsing mee te nemen:
if ($arg =~ /^--(\w+)=?(.*)/)
en als $val leeg is, de volgende element nemen.
Hoe gaat Perl om met argumenten die spaties bevatten?
Perl splitst de argumenten binnen @ARGV niet op spaties, alle splitsing wordt door de shell gedaan. Daarom "--foo=bar baz" komt als twee verschillende elementen aan, tenzij de string in aanhalingstekens wordt gezet in de commandoregel. Dit moet in acht worden genomen en altijd van de gebruiker worden vereist om spaties te ontsnappen.
Kan @ARGV worden gemodificeerd met shift, zonder de originele argumenten te verliezen?
Shift verandert de array zelf, de originele lijst van argumenten kan niet worden hersteld. Als het nodig is om de oorspronkelijke inhoud van @ARGV te behouden, moet deze van tevoren worden gekloond:
my @original_argv = @ARGV;
Het script verwerkte alleen sleutels in de vorm '--foo=bar', terwijl '--foo bar' werd genegeerd, en viel met een fout wanneer er geen waarde was.
Voordelen:
Nadelen:
We hebben de verwerking van beide syntaxis toegevoegd en de lengte van @ARGV gecontroleerd, en schakelvlaggen toegestaan.
Voordelen:
Nadelen: