표준 출력에 일부 문자열이 나타날 때까지 루프에서 명령을 어떻게 실행합니까?

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

  •  02-07-2019
  •  | 
  •  

문제

나는 stdout에서 어떤 문자열을 관찰할 때까지 루프에서 명령을 실행한 다음 중지할 수 있는 Perl, Ruby, bash 등의 사소한 단일 라이너가 있다고 확신합니다.이상적으로는 stdout도 캡처하고 싶지만 콘솔로 사용한다면 그것으로 충분할 수 있습니다.

현재 문제의 특정 환경은 RedHat Linux이지만 때로는 Mac에서도 동일한 것이 필요합니다.따라서 일반적인 것과 *nixy가 가장 좋습니다.Windows에 대해서는 신경 쓰지 마십시오. 아마도 *nixy는 cygwin에서 작동할 것입니다.

업데이트:"어떤 문자열을 관찰한다"는 것은 "stdout이 어떤 문자열이다"가 아니라 "stdout에 어떤 문자열이 포함되어 있다"는 뜻입니다.

도움이 되었습니까?

해결책

Perl에서 :

#!/usr/local/bin/perl -w

if (@ARGV != 2)
{
    print "Usage: watchit.pl <cmd> <str>\n";
    exit(1);
}

$cmd = $ARGV[0];
$str = $ARGV[1];

while (1)
{
    my $output = `$cmd`;
    print $output; # or dump to file if desired
    if ($output =~ /$str/)
    {
        exit(0);
    }
}

예시:

[bash$] ./watchit.pl ls stop
watchit.pl
watchit.pl~
watchit.pl
watchit.pl~
... # from another terminal type "touch stop"
stop 
watchit.pl
watchit.pl~

그래도 잠을 자고 싶을 수도 있습니다.

다른 팁

이 작업을 수행하는 방법에는 여러 가지가 있습니다. 첫 번째는 다음과 같습니다.

OUTPUT=""; 
while [ `echo $OUTPUT | grep -c somestring` = 0 ]; do 
  OUTPUT=`$cmd`; 
done

여기서 $ cmd가 실행하라는 명령입니다.

이를 위해서는 Bash 함수 버전이 있으므로 인터랙티브 쉘에서 정기적으로 호출하려는 경우 더 쉽게 호출 할 수 있습니다.

function run_until () {
  OUTPUT="";
  while [ `echo $OUTPUT | grep -c $2` = 0 ]; do
    OUTPUT=`$1`;
    echo $OUTPUT;
  done
}

면책 조항 : 명령에 많은 인수가 있거나 문자열에 특수 숯이 포함 된 경우, 약간의 테스트 만하면 추가 탈출 등을 수행해야 할 수도 있습니다.

편집하다: Adam의 의견의 피드백을 기반으로 - 만약 당신이 ~하지 않다 어떤 이유로 든 출력이 필요합니다 (즉, 출력을 표시하지 않으려면)이 짧은 버전을 사용할 수 있으며 백티크 사용량이 적으므로 오버 헤드가 적습니다.

OUTPUT=0; 
while [ "$OUTPUT" = 0 ]; do 
  OUTPUT=`$cmd | grep -c somestring`;
done

배쉬 기능 버전도 :

function run_until () {
  OUTPUT=0; 
  while [ "$OUTPUT" = 0 ]; do 
    OUTPUT=`$1 | grep -c $2`; 
  done
}

여기에 언급 된 간단한 Perl One-Liner를 보지 못한 것에 놀랐습니다.

perl -e 'do { sleep(1); $_ = `command`; print $_; } until (m/search/);'

Perl은 이와 같은 것들에게 정말 좋은 언어입니다. "명령"을 반복적으로 실행하려는 명령으로 바꾸십시오. "검색"을 검색하려는 것으로 바꾸십시오. 슬래시로 무언가를 검색하려면 교체하십시오. m/search/ ~와 함께 m#search 문자열 /es#.

또한 Perl은 Win32를 포함하여 다양한 플랫폼에서 실행되며 PERL 설치가있는 곳마다 작동합니다. 명령을 적절하게 변경하십시오.

grep -c 99999 경기에 대한 99999 컨텍스트 라인을 인쇄합니다 (이것으로 충분할 것이라고 가정합니다) :

while true; do /some/command | grep expected -C 99999 && break; done

또는

until /some/command | grep expected -C 9999; do echo -n .; done

... 이것은 진보를 나타 내기 위해 멋진 점을 인쇄합니다.

while (/bin/true); do
  OUTPUT=`/some/command`
  if [[ "x$OUTPUT" != "x" ]]; then
    echo $OUTPUT
    break
  fi

  sleep 1
done

편집하다:내 원래 대답은 "일부 문자열"이 "모든 문자열"을 의미한다고 가정했습니다.특정 항목을 찾아야 한다면 Perl이 최선의 선택일 것입니다. 왜냐하면 REGEX 일치와 관련하여 Perl을 능가할 수 있는 것은 거의 없기 때문입니다.

그러나 어떤 이유로든 Perl을 사용할 수 없는 경우(Perl이 대부분의 Linux 배포판에 있을 것으로 예상할 수 있지만 Perl을 사용할 수 없더라도 사용자에게 Perl을 설치하도록 강요하는 사람은 없습니다) 다음의 도움을 받아 수행할 수 있습니다. grep.그러나 지금까지 본 grep 솔루션 중 일부는 차선책입니다(필요한 것보다 느립니다).그런 경우에는 다음을 수행하는 것이 좋습니다.

MATCH=''; while [[ "e$MATCH" == "e" ]]; do MATCH=`COMMAND | grep "SOME_STRING"`; done; echo $MATCH

바꾸다 명령 실제로 실행 명령을 사용하여 SOME_STRING 검색할 문자열로.COMMAND의 출력에서 ​​SOME_STRING이 발견되면 루프가 중지되고 SOME_STRING이 발견된 출력을 인쇄합니다.

원래 답변:

아마도 최선의 해결책은 아닐 것입니다. (저는 훌륭한 bash 프로그래머는 아닙니다.) 작동할 것입니다 :-P

RUN=''; while [[ "e$RUN" == "e" ]]; do RUN=`XXXX`; done ; echo $RUN

XXXX를 명령 호출로 바꾸십시오."를 사용해보십시오에코" 그러면 결코 반환되지 않습니다(echo는 표준 출력에 아무 것도 인쇄하지 않으므로). 그러나 "에코 테스트" 한번에 종료되고 최종적으로 테스트가 출력됩니다.

CONT=1; while [ $CONT -gt 0 ]; do $CMD | tee -a $FILE | grep -q $REGEXP; CONT=$? ; done

tee 명령은 데이터를 계속 전달하면서 파이프의 stdout을 캡처할 수 있습니다. -a 매번 덮어쓰는 대신 파일에 추가합니다. grep -q ~ 할 것이다 return 0 경기가 있었다면, 1 그렇지 않으면 stdout에 아무것도 쓰지 않습니다. $? 이전 명령의 반환 값이므로 $CONT 이 경우 grep의 반환 값이 됩니다.

이것을하는 간단한 방법은 것입니다

until `/some/command`
do
  sleep 1
done

명령 주변의 백 티크가 until 명령의 종료 값을 테스트하기보다는 일부 출력을 반환 할 수 있습니다.

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