Frage

Das Problem ist, dass ich n Befehlszeilenargumente habe. Es wird immer mindestens 2 sein, die maximale Zahl ist jedoch unbegrenzt. Das erste Argument gibt einen Betriebsmodus an und die zweite ist eine Datei zu verarbeiten. Das dritte durch NTH sind die Dinge, die der Datei zu tun sind (was möglicherweise keine sein könnte, da der Benutzer möglicherweise nur die Datei reinigen möchte, die erledigt ist, wenn Sie sie nur 2 Argumente übergeben).

Ich schaue mir die Methoden an, die mir in Perl zur Arbeit mit Arrays zur Verfügung stehen, aber ich bin mir nicht sicher, wie es die "Beuligkeit" -Iteration von Punkt 3 bis zum Ende meines Arrays ist.

Einige Optionen, die ich gesehen habe:

  • Pop vom Ende des Arrays, bis ich ein Element finde, das nicht mit "-" beginnt (da der Dateipfad nicht mit einem "-" beginnt, obwohl ich vermute, dass es möglicherweise Probleme verursachen könnte).
  • Schalten Sie das Array zweimal, um die ersten beiden Elemente zu entfernen. Was auch immer ich übrig bin, ich kann einfach wiederholen, wenn seine Größe mindestens 1 beträgt.

Ich mag die zweite Option, aber ich weiß nicht, ob sie bekehrt ist. Und da ich versuche, Perl zu lernen, kann ich genauso gut den richtigen Weg lernen, Dinge in Perl zu tun.

War es hilfreich?

Lösung

Abgesehen von der Verwendung von Getopt -Modul, wie Sinan schrieb, würde ich wahrscheinlich gehen:

my ( $operation, $file, @things ) = @ARGV;

Und dann können Sie:

for my $thing_to_do ( @things ) {
...
}

Andere Tipps

IMHO, die Beuligkeit, das zu erreichen, was Sie brauchen, wäre, einen der zu verwenden Getopt -Module auf CPAN.

Wenn Sie es immer noch von Hand tun möchten, würde ich mich für die zweite Option entscheiden (dies ähnelt dem Umgang mit dem ersten Argument eines Methodenaufrufs):

die "Must provide filename and operation\n" unless @ARGV >= 2;

my $op = shift @ARGV;
my $file = shift @ARGV;

if ( @ARGV ) {
    # handle the other arguments;
}

Ich würde höchst Verwenden Sie die Verwendung Getopt :: Long Für Parsen -Befehlszeilenargumente. Es ist ein Standardmodul, es funktioniert fantastisch und macht genau das, was Sie versuchen, ein Kinderspiel zu machen.

use strict;
use warnings;
use Getopt::Long;

my $first_option = undef;
my $second_option = undef;

GetOptions ('first-option=s' => \$first_option, 
            'second-option=s' => \$second_option);

die "Didn't pass in first-option, must be xxxyyyzzz."
    if ! defined $first_option;
die "Didn't pass in second-option, must be aaabbbccc."
    if ! defined $second_option;

foreach my $arg (@ARGV) {
    ...
}

Auf diese Weise haben Sie einen langen Optionsnamen und füllen die Informationen automatisch in Variablen für Sie aus und ermöglichen es, sie zu testen. Sie können sogar später zusätzliche Befehle hinzufügen, ohne die Argumente zusätzliche Analysen zu erstellen, z. B. das Hinzufügen einer "Version" oder einer "Hilfe" -Option:

# adding these to the above example...
my $VERSION = '1.000';
sub print_help { ... }

# ...and replacing the previous GetOptions with this...
GetOptions ('first-option=s' => \$first_option, 
            'second-option=s' => \$second_option)
            'version' => sub { print "Running version $VERSION"; exit 1 },
            'help' => sub { print_help(); exit 2 } );

Dann können Sie es in der Befehlszeile verwenden -, --, der erste Brief oder die gesamte Option, und GetOptions Findet alles für Sie. Es macht Ihr Programm robuster und einfacher herauszufinden. Es ist "erraten", das man sagen könnte. Das Beste daran ist, dass Sie nie Ihren Code ändern müssen, der verarbeitet @ARGV, Weil GetOptions wird sich um all das Setup für Sie kümmern.

Die Standardmethode, um Dinge in Perl zu tun, ist über CPAN.

Meine erste Wahl wäre also Getopt :: Long. Es gibt auch ein Tutorial über Devshed: Verarbeitungsbefehlsleitungsoptionen mit Perl

Sie können a verwenden Scheibe um den 2. zu extrahieren. Zum Beispiel: zum Beispiel: zum Beispiel:

[dsm@localhost:~]$ perl -le 'print join ", ", @ARGV[2..$#ARGV];' 1 2 3 4 5 6 7 8 9 10 00
3, 4, 5, 6, 7, 8, 9, 10, 00
[dsm@localhost:~]$ 

Sie sollten jedoch wahrscheinlich verwenden shift (oder noch besser, GetOpt::Long)

Die Antwort von Deepesz ist eine gute Möglichkeit.

An Ihrer zweiten Option ist auch nichts auszusetzen:

my $op     = shift; # implicit shift from @ARGV
my $file   = shift; 
my @things = @ARGV;

# iterate over @things;

Sie können auch das Kopieren überspringen @ARGV hinein @things und arbeiten direkt daran. Wenn das Skript jedoch nicht sehr kurz, sehr einfach ist und im Laufe der Zeit wahrscheinlich nicht komplexer wird, würde ich es vermeiden, zu viele Abkürzungen vorzunehmen.

Ob Sie den Ansatz von Deepesz wählen, ist größtenteils eine Frage des Geschmacks.

Die Entscheidung, was besser ist, ist wirklich eine Frage der Philosophie. Der Kern des Problems ist, ob Sie Globale wie ändern sollten @ARGV. Einige würden sagen, es ist keine große Sache, solange es auf gut sichtbare Weise gemacht wird. Andere würden sich für das Verlassen argumentieren @ARGV unberührt.

Beachten Sie niemanden, der sich aufgrund von Geschwindigkeits- oder Speicherproblemen für die eine oder andere Option ausspricht. Das @ARGV Das Array ist durch die meisten Shells auf eine sehr kleine Größe begrenzt und daher ist keine signifikante Optimierung verfügbar, indem eine Methode über die andere verwendet wird.

Getopt :: Long, Wie bereits erwähnt, ist auch eine ausgezeichnete Wahl.

Schauen Sie sich an Moosex :: Getopt Weil es Ihren Appetit auf noch mehr Dinge durchführen kann Elch!.

Beispiel für Moosex :: GetOpt:

# getopt.pl

{
    package MyOptions;
    use Moose;
    with 'MooseX::Getopt';

    has oper   => ( is => 'rw', isa => 'Int', documentation => 'op doc stuff' );
    has file   => ( is => 'rw', isa => 'Str', documentation => 'about file' );
    has things => ( is => 'rw', isa => 'ArrayRef', default => sub {[]} );

    no Moose;
}

my $app = MyOptions->new_with_options;

for my $thing (@{ $app->things }) {
    print $app->file, " : ", $thing, "\n";
}

# => file.txt : item1
# => file.txt : item2
# => file.txt : item3

Wird das oben genannte erzeugen, wenn er wie so ausgeführt wird:

perl getopt.pl --oper 1 -file file.txt -theings item1 -Things item2 -Things Item3


Diese Elchtypen werden überprüft ... ./getopt --oper "not a number" produziert:

Value "not a number" invalid for option oper (number expected)

Und kostenlos bekommen Sie immer eine Nutzungsliste ;-)

usage: getopt.pl [long options...]
         --file         bit about file
         --oper         op doc stuff
         --things    

/I3az/

Für den allgemeineren Fall mit jedem Array:

for(my $i=2; $i<@array; $i++) {
    print "$array[$i]\n";
}

Diese schaltet sich durch das Array ab, beginnend mit dem dritten Element (Index 2). Das spezifische Beispiel, das Sie angegeben haben, ist die Antwort von Depesz die unkomplizierteste und beste.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top