Domanda

Il problema è che ho n argomenti della riga di comando.Ce ne saranno sempre almeno 2, tuttavia il numero massimo è illimitato.Il primo argomento specifica una modalità operativa e il secondo è un file da elaborare.Dalla terza all'ennesima sono le cose da fare sul file (che potrebbe non essere nessuna, poiché l'utente potrebbe semplicemente voler pulire il file, cosa che viene fatta se gli passi solo 2 argomenti).

Sto esaminando i metodi a mia disposizione in Perl per lavorare con gli array, ma non sono sicuro di quale sia il modo "Perlish" di scorrere dall'elemento 3 alla fine del mio array.

Alcune opzioni che ho visto:

  • Pop dalla fine dell'array finché non trovo un elemento che non inizia con "-" (poiché il percorso del file non inizia con "-", anche se suppongo che potrebbe, il che potrebbe causare problemi).
  • Sposta l'array due volte per rimuovere i primi due elementi.Qualunque cosa mi rimanga, posso semplicemente ripetere l'iterazione, se la sua dimensione è almeno 1.

Mi piace la seconda opzione, ma non so se è Perlish.E poiché sto cercando di imparare Perl, potrei anche imparare il modo giusto di fare le cose in Perl.

È stato utile?

Soluzione

Oltre a utilizzare il modulo Getopt come scrisse Sinan, probabilmente andare con:

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

E poi è possibile:

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

Altri suggerimenti

secondo me, il modo in cui la Perl di realizzare ciò che è necessario sarebbe quella di utilizzare uno dei I moduli getopt su CPAN .

Se si desidera continuare a farlo a mano, vorrei andare per la seconda opzione (questo è simile al modo in cui gestiamo il primo argomento di una chiamata di metodo):

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

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

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

Vorrei altamente Getopt :: Long per il parsing argomenti della riga di comando. Si tratta di un modulo standard, funziona impressionante, e fa esattamente quello che stai cercando di fare un gioco da ragazzi.

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) {
    ...
}

Questo ti permette di avere un nome di opzione a lungo, e automaticamente riempie le informazioni in variabili per voi, e vi permette di testare esso. Esso consente anche di aggiungere comandi extra dopo, senza dover fare alcuna analisi in più degli argomenti, come l'aggiunta di una versione '' o un'opzione di 'aiuto':

# 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 } );

Quindi, è possibile richiamare sulla riga di comando utilizzando -, --, la prima lettera, o l'intera opzione e GetOptions figure tutto per voi. Rende il vostro programma più robusto e più facile da capire; è più "indovinare" si potrebbe dire. La parte migliore è che non si deve modificare il codice che elabora @ARGV, perché GetOptions si prenderà cura di tutto ciò che l'installazione per voi.

Il modo più normale di fare le cose in Perl è attraverso CPAN.

Così la mia prima scelta sarebbe Getopt :: Long . C'è anche un tutorial su DevShed: Processing Opzioni riga di comando con Perl

Puoi usare a fetta per estrarre il 2°.agli ultimi elementi, ad esempio:

[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:~]$ 

tuttavia, probabilmente dovresti usare shift (o meglio ancora GetOpt::Long)

deepesz risposta è un buon modo per andare.

C'è anche niente di sbagliato con la vostra seconda opzione:

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

# iterate over @things;

Si potrebbe anche saltare la copia @ARGV in @things e lavorare direttamente su di essa. Tuttavia, a meno che lo script è molto breve, molto semplice, ed è improbabile che crescere di più complesso nel corso del tempo, vorrei evitare di prendere troppi tagli corti.

Se si sceglie l'approccio deepesz' o questo è in gran parte una questione di gusto.

La decisione che è meglio è davvero una questione di filosofia. Il nodo della questione è se è necessario modificare globali come @ARGV. Qualcuno potrebbe dire che è un grosso problema fintanto che si è fatto in un modo molto visibile. Altri sostengono a favore di lasciare @ARGV intatta.

Non prestare attenzione a chiunque sostenendo a favore di un'opzione o l'altro a causa di problemi di velocità o di memoria. L'array @ARGV è limitata dalla maggior parte delle shell ad una dimensione molto piccola e quindi non significativa ottimizzazione è disponibile utilizzando un metodo rispetto all'altro.

Getopt :: Long , come è stato detto è una scelta eccellente, troppo .

Do un'occhiata a MooseX :: Getopt perché può stimolare la tua appetito per le cose ancora più Moosey! .

Esempio di 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

Produrrà quanto sopra, quando eseguito in questo modo:

  

perl getopt.pl --oper 1 --file file.txt --things voce1 --things item2 --things item3

Questi tipi Moose vengono controllati ... ./getopt --oper "not a number" produce:

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

E per libero si ottiene sempre una lista utilizzo; -)

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

/ I3az /

Per il caso più generale di qualsiasi array:

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

Che scorre l'array, iniziando con il terzo elemento (indice 2). Ovviamente, l'esempio specifico si specifiy, la risposta di depesz è la più semplice e migliore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top