¿Cómo puede el sistema de Perl() imprimir el comando que está ejecutando?

StackOverflow https://stackoverflow.com/questions/17225

  •  08-06-2019
  •  | 
  •  

Pregunta

En Perl, puede ejecutar comandos del sistema usando system() o `` (comillas invertidas).Incluso puedes capturar la salida del comando en una variable.Sin embargo, esto oculta la ejecución del programa en segundo plano para que la persona que ejecuta el script no pueda verlo.

Normalmente esto es útil, pero a veces quiero ver qué sucede detrás de escena.¿Cómo se hace para que los comandos ejecutados se impriman en la terminal y la salida de esos programas se imprima en la terminal?Este sería el .bat equivalente a "@echo activado".

¿Fue útil?

Solución

Según tengo entendido, system() imprimirá el resultado del comando, pero no lo asignará.P.ej.

[daniel@tux /]$ perl -e '$ls = system("ls"); print "Result: $ls\n"'
bin   dev  home  lost+found  misc  net  proc  sbin     srv  System  tools  var
boot  etc  lib   media       mnt   opt  root  selinux  sys  tmp     usr
Result: 0

Las comillas invertidas capturarán el resultado del comando y no lo imprimirán:

[daniel@tux /]$ perl -e '$ls = `ls`; print "Result: $ls\n"'
Result: bin
boot
dev
etc
home
lib

etc...

Actualizar: Si también desea imprimir el nombre del comando que se está ejecutando en el sistema (), creo que RuddEl enfoque es bueno.Repetido aquí para consolidación:

sub execute {
    my $cmd = shift;
    print "$cmd\n";
    system($cmd);
}

my $cmd = $ARGV[0];
execute($cmd);

Otros consejos

No conozco ninguna forma predeterminada de hacer esto, pero puedes definir una subrutina para que lo haga por ti:

sub execute {
    my $cmd = shift;
    print "$cmd\n";
    system($cmd);
}

my $cmd = $ARGV[0];
execute($cmd);

Y luego verlo en acción:

pbook:~/foo rudd$ perl foo.pl ls
ls
file1   file2   foo.pl

Utilice abierto en su lugar.Luego puede capturar el resultado del comando.

open(LS,"|ls");
print LS;

Aquí hay una ejecución actualizada que imprimirá los resultados y los devolverá:

sub execute {
  my $cmd = shift;
  print "$cmd\n";
  my $ret = `$cmd`;
  print $ret;
  return $ret;
}

Mmmm, es interesante ver cómo diferentes personas responden de diferentes maneras.me parece como mk y Daniel Fone lo interpretó como querer ver/manipular la salida estándar del comando (ninguna de sus soluciones captura stderr fwiw).Creo Rudd Me acerqué.Un giro que podría darle a la respuesta de Rudd es sobrescribir el comando system() integrado con su propia versión para no tener que reescribir el código existente para usar su comando ejecutar().

usando su subejecutar() de la publicación de Rudd, podrías tener algo como esto en la parte superior de tu código:

if ($DEBUG) {
   *{"CORE::GLOBAL::system"} = \&{"main::execute"};
}

Creo que funcionará, pero debo admitir que esto es vudú y ha pasado un tiempo desde que escribí este código.Aquí está el código que escribí hace años para interceptar llamadas al sistema a nivel local (espacio de nombres de llamadas) o global en el momento de carga del módulo:

  # importing into either the calling or global namespace _must_ be
  # done from import().  Doing it elsewhere will not have desired results.
  delete($opts{handle_system});
  if ($do_system) {
    if ($do_system eq 'local') {
      *{"$callpkg\::system"} = \&{"$_package\::system"};
    } else {
      *{"CORE::GLOBAL::system"} = \&{"$_package\::system"};
    }
  }

Otra técnica para combinar con las otras mencionadas en las respuestas es utilizar el tee dominio.Por ejemplo:

open(F, "ls | tee /dev/tty |");
while (<F>) {
    print length($_), "\n";
}
close(F);

Esto imprimirá los archivos en el directorio actual (como consecuencia de tee /dev/tty) y también imprima la longitud de cada nombre de archivo leído.

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