Die Verarbeitung von Befehlszeilenargumenten erfolgt über das eingebaute Array @ARGV, das alle Parameter enthält, die dem Skript beim Start übergeben werden (außer dem Namen des Skripts selbst). Dies ist der grundlegende Weg für alle CLI Perl-Anwendungen, aber es gibt viele Nuancen, die mit Datentypen, Kodierung, der Trennung von Parametern und den Fallstricken beim automatischen Lesen von Dateien zu tun haben.
Seit den ersten Versionen repräsentiert das Array @ARGV den Standard-"Einstieg" in die Startargumente, ähnlich wie argv[] in C. Allerdings hat Perl, als Sprache für allgemeine Zwecke und Textaufgaben, viele zusätzliche Tricks eingeführt – zum Beispiel der Ausdruck <>, der "verbunden" ist mit dem Inhalt von @ARGV, wodurch es möglich ist, Dateien, die als Argumente aufgeführt sind, sofort zu lesen.
Das triviale Lesen von @ARGV reicht nur für einfache Fälle aus. Bei komplexen CLI-Anwendungen entsteht die Herausforderung, Optionen zu verarbeiten (z.B. --help, -o file). Hier wird das einfache Lesen von Daten nach Indizes unsicher und unpraktisch. Es wird noch schwieriger, wenn Argumente Leerzeichen, nicht standardmäßige Zeichen oder unterschiedliche Kodierungen enthalten. Außerdem ergeben sich Fragen zur automatischen Öffnung von Dateien über den Operator <> und unerwartetem Verhalten, wenn Elemente von @ARGV gleich sind, z.B. "-" (stdin).
Einfaches Lesen von Argumenten:
foreach my $arg (@ARGV) { print "Arg: $arg "; }
Normalerweise werden für Optionen spezielle Module wie Getopt::Long verwendet:
use Getopt::Long; my $help; GetOptions('help' => \$help);
Um den Inhalt aller Dateien aus @ARGV zu lesen, kann man den Inhalt der Dateien sofort in einer Schleife lesen:
while (<>) { print; }
Was passiert, wenn eines der Befehlszeilenargumente nur einen Bindestrich (-) enthält?
In diesem Fall interpretiert Perl bei Verwendung des Operators <> den '-' als Standard-Eingabe (stdin) und nicht als Dateinamen.
perl script.pl - file.txt # Zuerst aus stdin lesen, dann aus file.txt
Kann man @ARGV innerhalb des Skripts sicher modifizieren?
Ja, das ist eine gängige Praxis, um bereits verarbeitete Argumente zu entfernen. In der Regel verbleiben nach der Verarbeitung von Optionen in @ARGV nur noch "nackte" Dateinamen oder nicht erkannte Parameter.
Muss man bei der Arbeit mit UTF-8-Argumenten in @ARGV encode/decode durchführen?
Das hängt von der Locale und der Umgebung ab. Standardmäßig konvertiert Perl die Kodierungen von @ARGV nicht, sondern akzeptiert sie "wie sie sind". Daher ist es ratsam, die Zeichenfolgen explizit mit Encode zu dekodieren, wenn man mit ihnen in Perl arbeiten möchte, falls die Dateinamen (oder Parameter) nicht-ASCII-Zeichen enthalten.
Ein Tool zum Parsen von Logs akzeptiert eine Liste von Dateien. Der Benutzer gibt versehentlich '-' an:
perl parse.pl - access.log
Als Ergebnis bleibt das Programm plötzlich stehen und wartet auf Eingaben von der Tastatur.
Vorteile:
Nachteile:
Ein CLI-Programm liest Argumente über Getopt::Long und verarbeitet explizit alle negativen Optionen, wobei in @ARGV nur Dateinamen verbleiben:
perl report.pl --input access.log --output report.txt
Vorteile:
Nachteile: