Mie Oct 22, 2008 10:50 pm
|
 |
RockoX
Perlero Nuevo

|
Registrado: 20 Ago 2008
Mensajes: 10
|
|
| Variables argumentativas |
|
|
Hola a todos
Me surgió la duda de las variables argumentativas, lo que yo quiero hacer es un script que trabaje por consola, o sea hacer algo como esto:
| Código: |
| C:\Perl>Code.pl -n |
Y que me compare el argumento "-n".
Estoy pensando en usar algo como esto, claro que está mal usado, aun no lo sé implementar:
| Perl: | #!/usr/bin/perl
if ($ARGV[0] == "-n") {
print "Normal. \n";
}
if ($ARGV[0] == "-o") {
print "Otro\n";
} |
Si alguien me pudiera orientar por favor. |
|
|
|

Jue Oct 23, 2008 3:24 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4239
Ubicación: Valladolid, España
|
|
|
|
|
Las comparaciones de cadenas de caracteres se hace con otros operadores lógicos: eq, ne, lt, gt y cmp.
En tu caso, sería así:
| Perl: | #!/usr/bin/perl
if ($ARGV[0] eq '-n') {
print "Normal. \n";
}
elsif ($ARGV[0] eq '-o') {
print "Otro\n";
} |
Más información en perlop, Operadores relacionales.
Otra opción es usar la opción '-s', que ofrece un rudimentario procesado de los argumentos. Así, con este programa:
| Perl: | #!/usr/bin/perl -s
print "n:[$n]\n";
print "o:[$o]\n"; | y lo ejecutamos:
| Código: |
explorer@joaquin:~/Documents/Desarrollo> ./programa.pl -n=hhh -o
n:[hhh]
o:[1] |
Fíjate que Perl asigna automáticamente el valor de las opciones que se le pasen.
Bueno, en caso de que uses strict (que naturalmente deberías usarlo), el programa quedaría así:
El único cambio importante es agregar la declaración de las variables $n y $o, como globales a la aplicación.
Más información en perlrun.
Y, finalmente, si necesitas más potencia, mira en CPAN por alguno de los muchos módulos de la rama Getopt. Los más famosos son Getopt::Std (incluido de base con Perl), Getopt::Simple, Getopt::Long y curiosos como Getopt::Auto y Getopt::Lazy. |
|

Jue Oct 23, 2008 10:58 pm
|
 |
RockoX
Perlero Nuevo

|
Registrado: 20 Ago 2008
Mensajes: 10
|
|
|
|
|
Muchas gracias por responder, explorer, me ayudó mucho tu respuesta, con lo que aprendí de lo que pusiste, y de el tutorial de Despliegue de fecha, hice este script, en necesidad de que no me gusta el comando DATE /T de Windows :
| Perl: | #!/usr/bin/perl
use strict;
use warnings;
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime(time);
if(! $ARGV[0]) {
print "Fecha.pl\n\n";
print "Modo de uso : \n";
print "fecha.pl [/time] [/mday] [/month] [/year] [/wday] [/yday]\n";
print "/time : Muestra la hora actual del sistema.\n";
print "/mday : Muestra el dia del mes.\n";
print "/month : Muestra el nombre del mes actual.\n";
print "/year : Muestra el año en curso.\n";
print "/wday : Muestra el dia de la semana.\n";
print "/yday : Muestra el numero del dia del año.\n";
exit;
}
if ($ARGV[0] eq '/time' || $ARGV[0] eq '/TIME') {
print "$hour:$min:$sec";
exit;
}
if ($ARGV[0] eq '/mday' || $ARGV[0] eq '/MDAY') {
print "$mday";
exit;
}
if ($ARGV[0] eq '/month' || $ARGV[0] eq '/MONTH') {
my $number = $mon;
for (; $number < 12; $number++ ) {
if ($number == 1) {print "Enero\n"; }
if ($number == 2) {print "Febrero\n"; }
if ($number == 3) {print "Marzo\n"; }
if ($number == 4) {print "Abril\n"; }
if ($number == 4) {print "Mayo\n"; }
if ($number == 5) {print "Junio\n"; }
if ($number == 6) {print "Julio\n"; }
if ($number == 7) {print "Agosto\n"; }
if ($number == 8) {print "Septiembre\n"; }
if ($number == 9) {print "Octubre\n"; }
if ($number == 10) {print "Noviembre\n"; }
if ($number == 11) {print "Diciembre\n"; }
exit;
}
}
if ($ARGV[0] eq '/year' || $ARGV[0] eq '/YEAR') {
system("echo %date:~6,4%");
exit;
}
if ($ARGV[0] eq '/wday' || $ARGV[0] eq '/WDAY') {
my $number = $wday;
if ($number == 1) {print "Lunes\n"; }
if ($number == 2) {print "Martes\n"; }
if ($number == 3) {print "Miercoles\n"; }
if ($number == 4) {print "Jueves\n"; }
if ($number == 5) {print "Viernes\n"; }
if ($number == 6) {print "Sabado\n"; }
if ($number == 0) {print "Domingo\n"; }
exit;
}
if ($ARGV[0] eq '/yday' || $ARGV[0] eq '/YDAY') {
print "$yday\n";
exit;
} |
Cualquier sugerencia es bien recibida. |
|

Vie Oct 24, 2008 3:55 am
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4239
Ubicación: Valladolid, España
|
|
|
|
|
No está mal el código, pero quiero que te fijes en lo siguiente:
* El uso de array ahorra muchas líneas. Fíjate en tus líneas que hay varios print() que hacen casi lo mismo. Me refiero a los de los meses y los días
* La comparación $ARGV[0] eq '/time' || $ARGV[0] eq '/TIME' es un caso muy bueno para reducirlo: a una sola comparación, ya que la diferencia es solo si está en mayúsculas o minúsculas
* La impresión de horas, minutos y segundos, cuando no tienen dos dígitos, queda descompensada
* No sé porque llamas a system() para saber la cifra del año si ya te lo da localtime()
Fíjate en esta variación:
| Perl: | 1 #!/usr/bin/perl -l
2 #use strict;
3 #use warnings;
4 #use diagnostics;
5
6 my @meses = qw( Enero Febrero Marzo Abril Mayo Junio Julio Agosto Septiembre Octubre Noviembre Diciembre );
7 my @dias = qw( Domingo Lunes Martes Miércoles Jueves Viernes Sábado );
8
9 my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = localtime;
10 $year += 1900;
11 $mon += 1;
12
13 if (! @ARGV) {
14 print <<END_OF_INFO;
15 Fecha.pl
16
17 Modo de uso :
18 fecha.pl [/time|/mday|/month|/year|/wday|/yday ]
19 / time : Muestra la hora actual del sistema
20 /mday : Muestra el día del mes
21 /month : Muestra el nombre del mes actual
22 /year : Muestra el año en curso
23 /wday : Muestra el día de la semana
24 /yday : Muestra el número del día del año
25 END_OF_INFO
26 }
27 elsif (lc($ARGV[0]) eq '/time') {
28 printf "%02d:%02d:%02d\n", $hour, $min, $sec;
29 }
30 elsif (lc($ARGV[0]) eq '/mday') {
31 print $mday;
32 }
33 elsif (lc($ARGV[0]) eq '/month') {
34 print $meses[$mon- 1]; # Los array se basan en 0
35 }
36 elsif (lc($ARGV[0]) eq '/year') {
37 print $year;
38 }
39 elsif (lc($ARGV[0]) eq '/wday') {
40 print $dias[$wday]; # $wday ya está basado en 0
41 }
42 elsif (lc($ARGV[0]) eq '/yday') {
43 print $yday;
44 }
45 else {
46 print 'Argumento desconocido. Ejecute el programa sin argumentos para ver la ayuda.';
47 }
48
49 __END__ |
Comentarios, según la línea
- 1.- Debido a que la mayor parte de las salidas del programa consisten en un print() de un texto terminado en un carácter de avance de línea, ponemos la opción '-l' para ahorrarnos poner ese fin de línea (somos muy vagos...)
- 6 y 7.- Guardamos la información en forma de array, que usaremos más tarde
- 9.- Quitamos la variable $istdst porque no la usamos en el resto del programa. Esto lo podemos hacer porque es la última de la lista de variables
- 10 y 11.- Ajustamos los valores reales de año y mes
- 14 a 25.- Sustituimos los print() del mensaje de información por uno solo, con la técnica de Here-doc
- 27 y siguientes.- Las comparaciones son así: pasamos el parámetro pasado por el usuario a minúsculas con la ayuda de la función lc(), y así solo tenemos que hacer una comparación
- 27 y siguientes.- Ponemos los 'if' en cascada, y nos ahorramos los exit(), ya que solo se ejecutará uno solo de los 'if'.
- 28.- Como las cifras de horas, minutos y segundos pueden tener un solo dígito, los formateamos con printf()
- 34 y 40.- El uso de array ahorra mucho código. Accedemos a la información que queremos usando los valores de mes y día como índices dentro de los array
- 45.- En caso de que el usuario pase un argumento desconocido, se lo decimos.
De todas maneras, tu programa está muy bien, y funciona. Te animo a que sigas practicando. Con la experiencia descubrirás nuevas posibilidades, y también ha descubrir y corregir errores.
Un ejemplo:
| Perl: | #!/usr/bin/perl
#use strict;
#use warnings;
#use diagnostics;
my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = localtime(time);
$year += 1900;
$mon += 1;
my @meses = qw( enero febrero marzo abril mayo junio
julio agosto septiembre octubre noviembre diciembre
);
my @dias = qw( domingo lunes martes miércoles jueves viernes sábado );
my %comandos = (
'/time' => [ 'Muestra la hora actual del sistema', sprintf "%02d:%02d:%02d", $hour, $min, $sec ],
'/mday' => [ 'Muestra el día del mes' , $mday ],
'/month'=> [ 'Muestra el nombre del mes actual' , $meses[$mon- 1] ],
'/year' => [ 'Muestra el año en curso' , $year ],
'/wday' => [ 'Muestra el día de la semana' , $dias[$wday] ],
'/yday' => [ 'Muestra el número del día del año' , $yday ],
);
if (@ARGV) {
my $arg = lc $ARGV[0];
if ($comandos{$arg}) {
print $comandos{$arg}[1], "\n";
exit 0; # Ha ido bien
}
}
print 'Modo de uso: fecha.pl [' . join('|', map {"[$_]"} sort keys %comandos) . "]\n";
for my $arg (sort keys %comandos) {
printf "%10s : %s\n", $arg, $comandos{$arg}[0];
}
exit 1; # Ha ido mal
__END__ | Aquí usamos el uso de un hash de array para ayudar a almacenar tanto los mensajes de ayuda como el resultado de cada uno.
E incluso:
| Perl: | #!/usr/bin/perl
#use strict;
#use warnings;
#use diagnostics;
use POSIX qw(strftime locale_h );
setlocale (LC_TIME, "es_ES");
my %comandos = (
'/time' => [ '%T', 'Muestra la hora actual del sistema' ],
'/mday' => [ '%d', 'Muestra el día del mes' ],
'/month'=> [ '%B', 'Muestra el nombre del mes actual' ],
'/year' => [ '%Y', 'Muestra el año en curso' ],
'/wday' => [ '%A', 'Muestra el día de la semana' ],
'/yday' => [ '%j', 'Muestra el número del día del año' ],
);
if (@ARGV) {
my $arg = lc $ARGV[0];
if ($comandos{$arg}) {
print strftime ($comandos{$arg}[0], localtime), "\n";
exit 0; # Ha ido bien
}
}
print 'Modo de uso: fecha.pl [' . join('|', map {"[$_]"} sort keys %comandos) . "]\n";
for my $arg (sort keys %comandos) {
printf "%10s : %s\n", $arg, $comandos{$arg}[1];
}
exit 1; # Ha ido mal
__END__ | Aquí usamos la función strftime() del módulo POSIX para que se encargue de todo el trabajo de cálculo de fechas y nombres de días y meses. Y con el añadido de 'locale_h' tenemos a nuestra disposición los 'locales' del sistema: con solo cambiar "es_ES" por "fr_FR" nuestro programa sacará las fechas en Francés:
| Código: |
explorer@joaquin:~/Documents/Desarrollo> fecha.pl /wday
vendredi |
Con "da_DK", en danés:
| Código: |
explorer@joaquin:~/Documents/Desarrollo> fecha.pl /wday
fredag |
Y cambiándolo por "ja_JP.eucjp", en japonés:
| Código: |
explorer@joaquin:~/Documents/Desarrollo> fecha.pl /wday
金曜日 |
(naturalmente, depende de que en tu sistema tenga soporte de japonés ) |
|

Vie Oct 24, 2008 10:04 am
|
 |
RockoX
Perlero Nuevo

|
Registrado: 20 Ago 2008
Mensajes: 10
|
|
|
|
|
En mi código llamé a system() porque no sabía cómo sacar solo el año, además de que me gusta también BATCH, pero viendo tu código, también lo podría implementar así:
| Perl: | my ($sec, $min, $hour, $mday, $mon, $year, $wday, $yday) = localtime;
print "". $year+ 1900; |
No tenía idea de la función qw(), ya me quedó un poco más clara.
Igual me gustó la forma de cambiar el $ARGV[0] a minúsculas y luego hacer la comparación.
No tenía idea de esto:
Resulta muy útil, me ahorra los print().
El primer código tuyo lo entendí, los demás requieren un poco más de estudio de mi parte
Me queda una pregunta, en tus códigos pones al principio:
| Perl: | #use strict;
#use warnings;
#use diagnostics;
|
¿Realmente esto si corre?, o sea, ¿sí se ejecuta?, ¿o son solo comentarios?
Saludos. |
|

Vie Oct 24, 2008 11:29 am
|
 |
RockoX
Perlero Nuevo

|
Registrado: 20 Ago 2008
Mensajes: 10
|
|
|
|
|
Ahora hice este otro script, para contar las líneas de un archivo, llamando la función por consola:
| Perl: | #!/usr/bin/perl
use strict;
use warnings;
if(! $ARGV[0]) {
print <<END_OF_INFO;
contlin.pl : Cuenta el número de líneas de un archivo.
Modo de uso :
contlin.pl Archivo.ext
por Leonardo Gutierrez R.
END_OF_INFO
exit;
}
open(TEXTO, "$ARGV[0]") or die "El archivo no existe, o no se pudo abrir.\n";
my @lineas = <TEXTO>;
print "" . $ #lineas+1;
close (TEXTO ); |
Aprendí a usar un poco el "die".
 |
|

Vie Oct 24, 2008 5:40 pm
|
 |
explorer
Moderador

|
Registrado: 24 Jul 2005
Mensajes: 4239
Ubicación: Valladolid, España
|
|
|
|
|
Del lo puedes dejar enPor eso en el primer programa, hago unpara dejarlo ya a su cifra correcta y no preocuparme luego más.
qw() no es en sí una 'función', sino una forma de entrecomillar. qw() sirve para crear listas de palabras. En lugar de escribir
| Perl: | @x = ('Hola', 32, 'abuela', 15); | podemos escribir, con menos pulsaciones:
| Perl: | @x = qw( Hola 32 abuela 15); |
En cuanto a las 3 líneas, sí, son comentarios. El resumen es: hay que descomentarlas mientras estamos creando el programa, pues Perl nos ayudará a encontrar los problemas. Yo suelo usarlas siempre. |
|
Powered by phpBB © 2001, 2005 phpBB Group
|