Сведения о вопросе

Ayrat

19:40, 16th August, 2020

Теги

perl   system    

Как может Perlsystem() напечатать команду, которую он выполняет?

Просмотров: 443   Ответов: 6

В Perl вы можете выполнять системные команды, используя system() или ` (backticks). Вы даже можете записать выходные данные команды в переменную. Однако это скрывает выполнение программы в фоновом режиме, так что человек, выполняющий ваш сценарий, не может его видеть.

Обычно это полезно, но иногда я хочу посмотреть, что происходит за кулисами. Как сделать так, чтобы выполняемые команды печатались на terminal, а выходные данные этих программ-на terminal? Это будет .bat эквивалент "@echo on".



  Сведения об ответе

#hash

03:09, 16th August, 2020

Я не знаю никакого способа сделать это по умолчанию, но вы можете определить подпрограмму, чтобы сделать это за вас:

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

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

А потом увидеть его в действии:

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


  Сведения об ответе

ITSME

08:24, 1st August, 2020

Как я понимаю, system() выведет результат выполнения команды, но не назначит его. Напр..

[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 будет захватывать выходные данные команды и не печатать их:

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

и т.д...

Update: если вы хотите также напечатать имя команды system(), я думаю, что подход Радда хорош. Повторяется здесь для консолидации:

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

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


  Сведения об ответе

прога

16:26, 7th August, 2020

Вместо этого используйте open. Затем вы можете захватить выходные данные команды.

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


  Сведения об ответе

baggs

10:32, 21st August, 2020

Вот обновленный execute, который будет печатать результаты и возвращать их:

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


  Сведения об ответе

lesha

02:35, 13th August, 2020

Хм, интересно, как разные люди отвечают на это по-разному. Мне кажется, что mk и Daniel Fone интерпретировали это как желание видеть / манипулировать stdout команды (ни одно из их решений не захватывает stderr fwiw). Мне кажется, Радд подошел ближе. Один из поворотов, который вы могли бы сделать в ответе Радда, - это перезаписать встроенную команду system() с вашей собственной версией, чтобы вам не пришлось переписывать существующий код, чтобы использовать его команду execute().

используя его execute() sub из сообщения Радда, вы можете иметь что-то вроде этого в верхней части вашего кода:

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

Я думаю, что это сработает, но я должен признать, что это вуду, и прошло некоторое время с тех пор, как я написал этот код. Вот код, который я написал много лет назад для перехвата системных вызовов на локальном (вызывающее пространство имен) или глобальном уровне во время загрузки модуля:

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


  Сведения об ответе

lats

06:56, 10th August, 2020

Еще один прием для объединения с другими, упомянутыми в ответах, заключается в использовании команды tee . Например:

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

Это позволит как распечатать файлы в текущем каталоге (как следствие tee /dev/tty), так и распечатать длину каждого прочитанного файла.


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться