Perl의 system()은 실행 중인 명령을 어떻게 인쇄할 수 있습니까?

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

  •  08-06-2019
  •  | 
  •  

문제

Perl에서는 system() 또는 ``(백틱)을 사용하여 시스템 명령을 실행할 수 있습니다.명령의 출력을 변수로 캡처할 수도 있습니다.그러나 이렇게 하면 스크립트를 실행하는 사람이 볼 수 없도록 백그라운드에서 프로그램 실행이 숨겨집니다.

일반적으로 이는 유용하지만 때로는 뒤에서 무슨 일이 일어나고 있는지 보고 싶습니다.실행된 명령이 터미널에 인쇄되고 해당 프로그램의 출력이 터미널에 인쇄되도록 하려면 어떻게 해야 합니까?이것은 .bat "@echo on"과 동일합니다.

도움이 되었습니까?

해결책

내가 이해한 대로 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

백틱은 명령의 출력을 캡처하고 인쇄하지 않습니다.

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

등...

업데이트: system()이 되는 명령의 이름도 인쇄하고 싶다면, 제 생각에는 러드의 접근 방식은 좋습니다.통합을 위해 여기에서 반복합니다.

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

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

다른 팁

나는 이 작업을 수행하는 기본 방법을 모르지만 이를 수행하는 서브루틴을 정의할 수 있습니다.

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

대신 open을 사용하세요.그런 다음 명령의 출력을 캡처할 수 있습니다.

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

다음은 결과를 인쇄하고 반환하는 업데이트된 실행입니다.

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

흠, 사람들이 서로 다른 방식으로 대답하는 것이 흥미롭습니다.내가 보기엔 처럼 보이는데 MK 그리고 다니엘 폰 명령의 stdout을 보거나 조작하려는 것으로 해석했습니다(두 솔루션 모두 stderr fwiw를 캡처하지 않음).제 생각에는 러드 가까워졌습니다.Rudd의 응답을 변형할 수 있는 한 가지 방법은 내장된 system() 명령을 자신의 버전으로 덮어쓰는 것입니다. 그러면 그의 Execute() 명령을 사용하기 위해 기존 코드를 다시 작성할 필요가 없습니다.

Rudd의 게시물에 있는 그의 Execute() 하위를 사용하면 코드 상단에 다음과 같은 내용을 가질 수 있습니다.

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

답변에 언급된 다른 기술과 결합하는 또 다른 기술은 다음을 사용하는 것입니다. tee 명령.예를 들어:

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

이것은 둘 다 현재 디렉토리의 파일을 인쇄합니다(다음의 결과로). tee /dev/tty) 또한 읽은 각 파일 이름의 길이를 인쇄합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top