Question

Le problème est que j'ai des arguments de ligne de commande n. Il y aura toujours au moins 2, mais le nombre maximal est sans bornes. Le premier argument spécifie un mode de fonctionnement et le second est un fichier à traiter. Le 3 à n sont les choses à faire pour le fichier (qui peut être pas, puisque l'utilisateur peut simplement vouloir nettoyer le fichier, ce qui se fait si vous passez juste 2 arguments).

Je suis à la recherche sur les méthodes disponibles pour m'en Perl pour travailler avec des tableaux, mais je ne suis pas sûr de ce que le chemin de itérer du point 3 à la fin de mon tableau « perlienne » est.

Quelques options que je l'ai vu:

  • Pop de la fin du tableau jusqu'à ce que je trouve un élément qui ne commence pas par « - » (depuis le chemin du fichier ne commence pas par un « - », même si je suppose qu'il pourrait, ce qui pourrait causer des problèmes).
  • Déplacer le réseau à deux reprises pour éliminer les deux premiers éléments. Tout ce que je suis parti avec je peux itérer sur, si sa taille est d'au moins 1.

J'aime la deuxième option, mais je ne sais pas si c'est perlienne. Et depuis que je suis en train d'apprendre Perl, je pourrais aussi bien apprendre la bonne façon de faire les choses en Perl.

Était-ce utile?

La solution

En plus d'utiliser le module Getopt comme l'a écrit Sinan, je ne serais probablement aller avec:

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

Et vous pouvez:

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

Autres conseils

à mon humble avis, la façon perlienne d'accomplir ce dont vous avez besoin serait d'utiliser l'un des Getopt modules sur CPAN .

Si vous voulez continuer à le faire à la main, je pencherais pour la deuxième option (ce qui est similaire à la façon dont nous traitons le premier argument d'un appel de méthode):

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

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

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

Je voudrais très vous recommandons d'utiliser Getopt :: Long pour analyser les arguments de ligne de commande. Il est un module standard, cela fonctionne génial, et fait exactement ce que vous essayez de faire un jeu d'enfant.

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

Cela vous permet d'avoir un nom de l'option, et remplit automatiquement les informations dans les variables pour vous, et vous permet de le tester. Il vous permet même d'ajouter des commandes supplémentaires plus tard, sans avoir à faire une analyse syntaxique supplémentaire des arguments, comme l'ajout d'une « version » ou une option « help »:

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

Ensuite, vous pouvez l'appeler sur la ligne de commande à l'aide -, --, la première lettre, ou l'option entière, et GetOptions tout pour vous chiffres. Il rend votre programme plus robuste et plus facile à comprendre; il est plus « devinables » vous pourriez dire. La meilleure partie est que vous ne devez changer votre code qui traite @ARGV, parce que GetOptions prendra soin de tout ce que l'installation pour vous.

La façon la plus classique de faire les choses en Perl est par CPAN.

Alors, mon premier choix serait Getopt :: long . Il y a aussi un tutoriel sur DevShed: traitement options de commande de ligne avec Perl

Vous pouvez utiliser un tranche pour extraire le 2ème. aux derniers éléments, par exemple:

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

cependant, vous devriez probablement utiliser shift (ou mieux encore, GetOpt::Long )

deepesz réponse est une bonne façon d'aller.

Il n'y a rien de mal avec votre deuxième option:

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

# iterate over @things;

Vous pouvez aussi sauter la copie @ARGV dans @things et travailler directement sur elle. Cependant, à moins que le script est très court, très simple, et peu susceptible de croître plus complexe au fil du temps, j'éviter de prendre trop de raccourcis.

Si vous choisissez approche « deepesz ou celui-ci est en grande partie une question de goût.

Décider ce qui est mieux est vraiment une question de philosophie. Le point crucial de la question est de savoir si vous devez modifier comme GLOBALS @ARGV. Certains diront qu'il n'y a pas grand-chose aussi longtemps que cela est fait d'une manière très visible. D'autres soutiendraient en faveur de laisser @ARGV intacte.

Ne faites pas attention à tous ceux qui plaidant en faveur d'une ou l'autre option en raison de problèmes de vitesse ou de la mémoire. Le tableau de @ARGV est limité par la plupart des coquilles à une très petite taille et donc pas d'optimisation significative est disponible en utilisant une méthode sur l'autre.

Getopt :: long , comme cela a été mentionné est un excellent choix aussi .

Ne jetez un oeil à MooseX :: Getopt car il peut vous mettre l'eau l'appétit pour les choses encore plus Moosey! .

Exemple de 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

Produira ci-dessus lorsqu'il est exécuté comme ceci:

  

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

Ces types d'orignaux sont contrôlés ... ./getopt --oper "not a number" produit:

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

Et gratuitement, vous obtenez toujours une liste d'utilisation; -)

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

/ I3az /

Pour le cas plus général avec un tableau:

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

Cette boucle à travers le réseau, en commençant par le troisième élément (indice 2). De toute évidence, l'exemple spécifique que vous spécifions, la réponse de depesz est le plus simple et mieux.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top