strawberry - ¿Cómo puedo convertir Perl one-liners en scripts completos?
perl windows (6)
Encuentro una gran cantidad de perl one-liners en línea. A veces quiero convertir estas frases de una sola línea en un script, porque de lo contrario me olvidaré de la sintaxis de la de una sola línea.
Por ejemplo, estoy usando el siguiente comando (de nagios.com ):
tail -f /var/log/nagios/nagios.log | perl -pe ''s/(/d+)/localtime($1)/e''
Me gustaría reemplazarlo con algo como esto:
tail -f /var/log/nagios/nagios.log | ~/bin/nagiostime.pl
Sin embargo, no puedo encontrar la mejor manera de lanzar rápidamente estas cosas en un script. ¿Alguien tiene una forma rápida de lanzar estas frases en un script Bash o Perl?
¡Eso es realmente fácil de almacenar en un guión!
#! /usr/bin/perl -p
s/(/d+)/localtime($1)/e
La opción -e
introduce el código de Perl que se ejecutará, que podría considerarse como un script en la línea de comandos, así que suéltelo y pegue el código en el cuerpo. Deje -p
en la línea shebang ( #!
).
En general, es más seguro atenerse a lo más un "grupo" de opciones en la línea de shebang. Si necesita más, siempre puede lanzar sus equivalentes dentro de un bloque BEGIN {}
.
No olvides chmod +x ~/bin/nagiostime.pl
Puedes ponerte un poco más sofisticado e incrustar la parte de la tail
también:
#! /usr/bin/perl -p
BEGIN {
die "Usage: $0 [ nagios-log ]/n" if @ARGV > 1;
my $log = @ARGV ? shift : "/var/log/nagios/nagios.log";
@ARGV = ("tail -f ''$log'' |");
}
s/(/d+)/localtime($1)/e
Esto funciona porque el código escrito para usted por -p
usa la open
"mágica" (2-argumento) de Perl que procesa tuberías especialmente.
Sin argumentos, transforma nagios.log
, pero también puede especificar un archivo de registro diferente, por ejemplo ,
$ ~/bin/nagiostime.pl /tmp/other-nagios.log
Echa un vistazo a perlrun :
-pag
hace que Perl asuma el siguiente bucle alrededor de tu programa, lo que lo hace iterar sobre los argumentos de nombre de archivo de forma similar a sed:
LINE: while (<>) { ... # your program goes here } continue { print or die "-p destination: $!/n"; }
Si un archivo nombrado por un argumento no se puede abrir por alguna razón, Perl le advierte al respecto y pasa al siguiente archivo. Tenga en cuenta que las líneas se imprimen automáticamente. Un error que se produce durante la impresión se considera fatal. Para suprimir la impresión use el interruptor -n. A -p anula un interruptor -n.
Los bloques BEGIN y END se pueden usar para capturar el control antes o después del bucle implícito, al igual que en awk.
Entonces, simplemente tome esta porción de código, inserte su código en la línea "# su programa va aquí", y viola, ¡su script está listo!
Por lo tanto, sería:
#!/usr/bin/perl -w
use strict; # or use 5.012 if you''ve got newer perls
while (<>) {
s/(/d+)/localtime($1)/e
} continue {
print or die "-p destination: $!/n";
}
Hay algunas buenas respuestas aquí si desea mantener el guión convertido de una sola línea y posiblemente ampliarlo, pero lo más simple que podría funcionar es simplemente:
#!/usr/bin/perl -p
s/(/d+)/localtime($1)/e
Perl reconocerá los parámetros en la línea de hashbang de la secuencia de comandos, por lo que en lugar de escribir el bucle completo, puede continuar haciendo el bucle implícito con -p.
Pero escribiendo el bucle explícitamente y usando -w y "use strict"; es bueno si planea usarlo como punto de partida para escribir un script más largo.
Puede convertir cualquier script de una línea de Perl en un script completo pasándolo por el backend del compilador B::Deparse
que genera el código fuente de Perl:
perl -MO=Deparse -pe ''s/(/d+)/localtime($1)/e''
salidas:
LINE: while (defined($_ = <ARGV>)) {
s/(/d+)/localtime($1);/e;
}
continue {
print $_;
}
La ventaja de este enfoque sobre la decodificación manual de las marcas de línea de comando es que esta es exactamente la forma en que Perl interpreta su script, por lo que no hay conjeturas. B::Deparse
es un módulo central, por lo que no hay nada que instalar.
Robert tiene la respuesta "real" anterior, pero no es muy práctico. El interruptor -p hace un poco de magia, y otras opciones tienen aún más magia (por ejemplo, verifique la lógica detrás de la bandera -i). En la práctica, simplemente haría una función / alias de bash para envolver el oneliner, en lugar de convertirlo en un script.
Alternativamente, aquí está tu oneliner como un script: :)
#!/usr/bin/bash
# takes any number of arguments: the filenames to pipe to the perl filter
tail -f $@ | perl -pe ''s/(/d+)/localtime($1)/e''
#!/usr/bin/env perl
while(<>) {
s/(/d+)/localtime($1)/e;
print;
}
El bucle while y la impresión es lo que -p hace automáticamente por ti.