ProgrammatieDevOps/CLI Perl ontwikkelaar

Hoe verwerkt Perl de commandoregel via @ARGV en welke subtiele punten kunnen zich voordoen bij het werken met scriptargumenten?

Slaag voor sollicitatiegesprekken met de Hintsage AI-assistent

Antwoord.

De verwerking van commandoregelargumenten vindt plaats via de ingebouwde array @ARGV, die alle parameters bevat die aan het script zijn doorgegeven bij de uitvoering (behalve de naam van het script zelf). Dit is de basismanier voor alle CLI Perl-toepassingen, maar er zijn veel nuances verbonden aan datatypen, codering, het splitsen van parameters en verborgen valkuilen bij het automatisch lezen van bestanden.

Achtergrond

Vanaf de eerste versies van Perl was de array @ARGV de standaard "toegangspunt" voor opstartargumenten, vergelijkbaar met argv[] in C. Echter, Perl, als een algemene programmeertaal voor teksttaken, heeft veel extra trucs toegevoegd — bijvoorbeeld de expressie <>, die "verbonden" is met de inhoud van @ARGV, waardoor het mogelijk is om bestanden die als argumenten zijn opgesomd, direct te lezen.

Probleem

Triviaal lezen van @ARGV is alleen geschikt voor eenvoudige gevallen. In complexe CLI-programma's komt de taak om opties te verwerken (zoals --help, -o file) naar voren. Hier wordt eenvoudig lezen van gegevens op indexen onveilig en ongemakkelijk. Het wordt nog ingewikkelder met het verwerken van argumenten die spaties, niet-standaard symbolen of in verschillende coderingen bevatten. Bovendien zijn er vragen bij het automatisch openen van bestanden via de operator <> en onverwacht gedrag als elementen van @ARGV gelijk zijn aan, bijvoorbeeld, "-" (stdin).

Oplossing

Lezen van eenvoudige argumenten:

foreach my $arg (@ARGV) { print "Arg: $arg "; }

Gewoonlijk wordt voor opties een speciale module Getopt::Long gebruikt:

use Getopt::Long; my $help; GetOptions('help' => \$help);

Voor het lezen van alle bestanden uit @ARGV kan de inhoud van bestanden direct via een lus worden gelezen:

while (<>) { print; }

Belangrijke kenmerken:

  • @ARGV — rauwe strings, alle parameters na de naam van het script, inclusief paden naar bestanden
  • De operator <> interpreteert @ARGV als een lijst van bestanden om te lezen
  • Voor commandoregelopties is het bij voorkeur om modules zoals Getopt::Long, Getopt::Std, etc. te gebruiken.

Vragen met een valstrik.

Wat gebeurt er als een van de commandoregelargumenten alleen een streepje (-) bevat?

In dit geval beschouwt Perl '-' als standaardinvoer (stdin) en niet als bestandsnaam bij gebruik van de operator <>.

perl script.pl - file.txt # Eerst lezen van stdin, daarna van file.txt

Is het veilig om @ARGV binnen het script te wijzigen?

Ja, dit is een standaardpraktijk om al verwerkte argumenten te verwijderen. Gewoonlijk blijven er na het verwerken van opties alleen nog "blote" bestandsnamen of niet-herkende parameters in @ARGV over.

Moet je encode/decode doen bij het werken met UTF-8-argumenten in @ARGV?

Dit hangt af van de locale en omgeving. Standaard converteert Perl de coderingen van @ARGV niet en accepteert deze "zoals ze zijn". Daarom, als bestandsnamen (of parameters) niet-ASCII-symbolen bevatten, is het wenselijk om de strings expliciet te decoderen met behulp van Encode, als je ermee wilt werken in Perl.

Veelvoorkomende fouten en anti-patronen

  • Handmatig parseren van scriptopties — gemakkelijk om fout te maken met positionele argumenten
  • Proberen een binaire file te lezen via <> leidt tot gegevenscorruptie
  • Het negeren van de noodzaak om parameters te decoderen bij internationalisatie

Voorbeeld uit het leven

Negatieve case

Een tool voor het parseren van logs accepteert een lijst van bestanden. De gebruiker geeft per ongeluk '-' op:

perl parse.pl - access.log

als resultaat stopte het programma plotseling en wachtte op invoer vanaf het toetsenbord.

Voordelen:

  • Snelle lezing van stdin is ook mogelijk

Nadelen:

  • Onvoorspelbaar voor beginners
  • Moeilijk uit te leggen waarom het "hangt"

Positieve case

Een CLI-programma leest argumenten via Getopt::Long en verwerkt expliciet alle minopties, waardoor alleen de bestandsnamen in @ARGV blijven:

perl report.pl --input access.log --output report.txt

Voordelen:

  • Voorspelbaar gedrag
  • Gebruiksgemak voor de gebruiker
  • Makkelijker te onderhouden

Nadelen:

  • Vereist meer code en aandacht
  • Het is nodig om specificaties voor alle opties op te stellen