Pregunta

El problema es que no tengo argumentos n de línea de comandos. No siempre van a ser por lo menos 2, sin embargo, el número máximo es ilimitado. El primer argumento especifica un modo de funcionamiento y el segundo es un archivo para procesar. La tercera través enésima son las cosas que hacer en el fichero (que podría haber ninguno, ya que el usuario sólo podría querer limpiar el archivo, que se realiza si sólo pasarlo 2 argumentos).

Estoy mirando los métodos disponibles para mí en Perl para trabajar con matrices, pero no estoy seguro de cuál es el camino "Perlish" de la iteración desde el punto 3 hasta el final de mi matriz es.

Algunas opciones que he visto:

  • Pop desde el final de la matriz hasta que encuentre un elemento que no comience con "-" (puesto que la ruta del archivo no comienza con un signo "-", aunque supongo que podría, que puede provocar problemas).
  • Shift la matriz dos veces para eliminar los dos primeros elementos. Lo que me queda sólo puedo iterar sobre si su tamaño es de al menos 1.

Me gusta la segunda opción, pero no sé si es Perlish. Y ya que estoy tratando de aprender Perl, que bien podría aprender la forma correcta de hacer las cosas en Perl.

¿Fue útil?

Solución

Aparte de usar el módulo Getopt como escribió Sinan, probablemente me iría con:

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

Y a continuación, se puede:

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

Otros consejos

En mi humilde opinión, la manera de llevar a cabo Perlish lo que necesita sería utilizar uno de los módulos getopt en CPAN .

Si aún desea hacerlo a mano, me gustaría ir por la segunda opción (esto es similar a la forma en que manejamos el primer argumento de una llamada de método):

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

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

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

Me muy Getopt :: Largo para analizar los argumentos de línea de comandos. Es un módulo estándar, funciona impresionante, y hace exactamente lo que estamos tratando de hacer una brisa.

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

Esto le permite disponer de un nombre de la opción, y automáticamente rellena la información en variables para usted, y le permite probarlo. Incluso le permite agregar comandos adicionales más tarde, y sin tener que hacer ningún análisis adicional de los argumentos, como la adición de una 'versión' o una opción de 'ayuda':

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

A continuación, se puede invocar en la línea de comandos usando -, --, la primera letra, o la opción completa, y GetOptions cifras que todo para usted. Esto hace que su programa más robusto y fácil de entender; es más "adivinar" que se podría decir. La mejor parte es que nunca tenga que cambiar su código que procesa @ARGV, porque GetOptions se hará cargo de todo lo que la configuración para usted.

La forma más estándar de hacer las cosas en Perl es a través de CPAN.

Así que mi primera opción sería Getopt :: largo . También hay un tutorial sobre DevShed: Procesamiento Opciones de línea de comandos con Perl

Puede utilizar un rebanada para extraer el segundo. a últimos elementos, por ejemplo:

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

Sin embargo, es probable que debe utilizar shift (o mejor aún, GetOpt::Long )

deepesz respuesta es una buena manera de ir.

También hay nada malo con su segunda opción:

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

# iterate over @things;

También puede omitir @ARGV copia en @things y trabajar directamente en él. Sin embargo, a menos que el guión es muy corto, muy simple, y es poco probable que crezca más complejas con el tiempo, evitaría tomar demasiados atajos.

Ya sea que elija el enfoque deepesz' o éste es en gran medida una cuestión de gusto.

La decisión sobre qué es mejor es realmente una cuestión de filosofía. El quid de la cuestión es si se debe modificar variables globales como @ARGV. Algunos dicen que no es gran cosa, siempre y cuando se haga de una manera muy visible. Otros argumentan a favor de dejar @ARGV intacta.

No preste atención a cualquier persona argumentando a favor de una u otra opción, debido a problemas de velocidad o de memoria. La matriz @ARGV está limitada por la mayoría de las cáscaras a un tamaño muy pequeño y por lo tanto no la optimización significativa está disponible mediante el uso de un método sobre el otro.

Getopt :: largo , como se ha mencionado es una excelente opción, también .

¿Tiene un vistazo a MooseX :: Getopt , ya que puede ir haciendo apetito por las cosas aún más Moosey! .

Ejemplo 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

producirá lo anterior cuando se ejecuta este modo:

  

Perl getopt.pl --oper 1 --file archivo.txt --things item1 --things item2 --things elemento3


Estos tipos se comprueban los alces ... ./getopt --oper "not a number" produce:

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

Y de forma gratuita siempre obtendrá una lista de uso; -)

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

/ I3az /

En el caso más general con cualquier matriz:

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

que los bucles a través de la matriz, empezando con el tercer elemento (índice 2). Obviamente, el ejemplo específico que specifiy, la respuesta de depesz es el más sencillo y mejor.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top