15

stdoutで文字列を観察するまでループでコマンドを実行し、その後停止するような、perl、ruby、bashを備えた簡単なワンライナーがあると確信しています。理想的には、stdoutもキャプチャしたいのですが、コンソールに接続する場合は、それで十分かもしれません。

現在問題となっている特定の環境はRedHatLinuxですが、Macでも同じことが必要になる場合があります。したがって、何か、一般的で*nixyが最適です。Windowsについては気にしないでください-おそらく*nixyはcygwinの下で機能します。

更新:「いくつかの文字列を観察する」とは、「stdoutはいくつかの文字列である」ではなく「stdoutにいくつかの文字列が含まれる」ことを意味することに注意してください。

4

8 に答える 8

13

パールでは:

#!/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~

ただし、そこに睡眠を追加したい場合があります。

于 2008-09-24T18:26:22.000 に答える
11

これを行うにはたくさんの方法があります。最初に頭に浮かんだのは次のとおりです。

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

BASH関数バージョンも:

function run_until () {
  OUTPUT=0; 
  while [ "$OUTPUT" = 0 ]; do 
    OUTPUT=`$1 | grep -c $2`; 
  done
}
于 2008-09-24T18:18:13.020 に答える
7

ここで言及されている簡単な Perl ワンライナーを見たことがないことに驚いています。

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

Perl は、このようなものに最適な言語です。「コマンド」を繰り返し実行するコマンドに置き換えます。「検索」を検索したいものに置き換えます。スラッシュを含むものを検索する場合は、文字列を にm/search/置き換えm#searchます/es#

また、Perl は Win32 を含む多くの異なるプラットフォームで実行され、これは Perl がインストールされている場所であればどこでも機能します。コマンドを適切に変更するだけです。

于 2008-10-02T03:39:29.247 に答える
6

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

...これにより、進行状況を示すためにいくつかの素敵なドットが出力されます。

于 2008-09-25T12:35:27.343 に答える
1
while (/bin/true); do
  OUTPUT=`/some/command`
  if [[ "x$OUTPUT" != "x" ]]; then
    echo $OUTPUT
    break
  fi

  sleep 1
done
于 2008-09-24T18:18:23.703 に答える
1

編集:私の最初の答えは、「いくつかの文字列」は「任意の文字列」を意味すると仮定していました。特定のものを探す必要がある場合は、正規表現のマッチングに関してPerlに勝るものはほとんどないため、Perlがおそらく最良の選択肢です。

ただし、何らかの理由でPerlを使用できない場合(PerlはほとんどのLinuxディストリビューションに存在することが期待できますが、Perlが利用できない場合でも、ユーザーにインストールを強制することはありません)、 grep。ただし、これまでに見たgrepソリューションのいくつかは最適ではありません(必要な速度よりも遅い)。その場合、私はむしろ次のことをしたいと思います:

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

COMMANDを実行する実際のコマンドに置き換え、 SOME_STRINGを検索する文字列に置き換えます。COMMANDの出力でSOME_STRINGが見つかった場合、ループは停止し、SOME_STRINGが見つかった出力を出力します。

元の回答:

おそらく最善の解決策ではありませんが(私は優れたbashプログラマーではありません)、それは機能します:-P

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

XXXXをコマンド呼び出しに置き換えるだけです。たとえば、「echo」を使用してみると、戻りません(echoはstdoutに何も出力しないため)。ただし、「echo test」を使用すると、すぐに終了し、最後にtestを出力します。

于 2008-09-24T18:21:39.127 に答える
1
CONT=1; while [ $CONT -gt 0 ]; do $CMD | tee -a $FILE | grep -q $REGEXP; CONT=$? ; done

tee コマンドは、データを渡しながら stdout をパイプでキャプチャし、-a毎回上書きするのではなく、ファイルに追加します。一致があった場合は、grep -qそれ以外の場合は stdout に何も書き込みません。は前のコマンドの戻り値なので、この場合は grep の戻り値になります。return 01$?$CONT

于 2008-09-24T22:46:58.927 に答える
0

これを行う簡単な方法は次のとおりです。

until `/some/command`
do
  sleep 1
done

コマンドの前後のバッククォートは、コマンドuntilの終了値をテストするのではなく、返される出力のテストを行います。

于 2008-09-24T23:10:30.930 に答える