Comment peut-Perl (système) impression de la commande qu'il est en cours d'exécution?

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

  •  08-06-2019
  •  | 
  •  

Question

En Perl, vous pouvez exécuter des commandes système à l'aide de system() ou ` (backticks).Vous pouvez même capturer la sortie de la commande dans une variable.Cependant, ce cache l'exécution du programme en arrière-plan, de sorte que la personne qui exécute votre script ne peut pas le voir.

Normalement, c'est utile, mais parfois, j'ai envie de voir ce qui se passe derrière les coulisses.Comment voulez-vous faire si les commandes exécutées sont imprimés à la borne, et de ces programmes de sortie imprimée vers le terminal?Ce serait la .bat l'équivalent de "@echo sur".

Était-ce utile?

La solution

Ce que je comprends, system() affichera le résultat de la commande, mais pas l'affecter.Par exemple.

[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

Backticks la capture à la sortie de la commande et de ne pas l'imprimer:

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

etc...

Mise à jour: Si vous souhaitez imprimer le nom de la commande system()'d ainsi, je pense Ruddl'approche est bonne.Repris ici, pour la consolidation:

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

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

Autres conseils

Je ne sais pas du tout par défaut de façon à ce faire, mais vous pouvez définir une sous-routine pour le faire pour vous:

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

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

Et puis le voir en action:

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

D'utilisation s'ouvre à la place.Ensuite, vous pouvez capturer la sortie de la commande.

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

Voici une mise à jour de l'exécuter à imprimer les résultats et de les retourner:

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

Hmm, intéressant de voir comment différentes personnes sont de répondre à cette façons différentes.Il me semble mk et Daniel Fone interprété comme voulant voir/manipuler la sortie standard de la commande (ni de leurs solutions de capture stderr fwiw).Je pense Rudd s'est rapproché.Un twist que vous pourriez faire sur Rudd réponse est à overwite intégré dans la commande system() avec votre propre version de sorte que vous ne pas avoir à réécrire le code existant pour utiliser son execute() de la commande.

à l'aide de son execute() sous de Rudd post, vous pourriez avoir quelque chose comme ça en haut de votre code:

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

Je pense que cela va fonctionner, mais je dois admettre que c'est le vaudou et il a été un moment depuis que j'ai écrit ce code.Voici le code que j'ai écrit il y a des années pour intercepter des appels système sur un local (l'appel de l'espace de noms) ou de niveau mondial au module de temps de chargement:

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

Une autre technique de la combiner avec d'autres mentionnés dans les réponses est d'utiliser la tee commande.Par exemple:

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

Cela permettra à la fois d'imprimer les fichiers dans le répertoire courant (comme une conséquence de tee /dev/tty) et aussi imprimer la longueur de chaque nom de fichier à lire.

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