我确定有一些带有perl,ruby,bash的简单单行程,无论是什么让我在循环中运行命令,直到我在stdout中观察到一些字符串,然后停止。理想情况下,我也想捕获stdout,但如果要进入控制台,这可能就足够了。

目前有问题的特定环境是RedHat Linux,但有时在Mac上也需要同样的东西。所以,通用和* nixy是最好的。不关心Windows - 可能是一个* nixy的东西可以在cygwin下工作。

更新:请注意,通过“观察一些字符串”我的意思是“stdout包含一些字符串”不是“stdout IS some string”。

有帮助吗?

解决方案

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函数版本,所以你可以更容易地调用它,如果它是你想要定期从交互式shell调用的东西:

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
}

我很惊讶我没有看到这里提到的简短的Perl单行程序:

perl -e 'do { sleep(1); 

我很惊讶我没有看到这里提到的简短的Perl单行程序:

<*>

对于像这样的东西,Perl是一个非常好的语言。替换“命令”使用您想要重复运行的命令。替换“搜索”用你想要搜索的内容。如果要搜索包含斜杠的内容,请将 m / search / 替换为 m#search 字符串,并带有 / es#

此外,Perl可以在许多不同的平台上运行,包括Win32,这将适用于Perl安装的任何地方。只需适当更改命令即可。

= `command`; print

我很惊讶我没有看到这里提到的简短的Perl单行程序:

<*>

对于像这样的东西,Perl是一个非常好的语言。替换“命令”使用您想要重复运行的命令。替换“搜索”用你想要搜索的内容。如果要搜索包含斜杠的内容,请将 m / search / 替换为 m#search 字符串,并带有 / es#

此外,Perl可以在许多不同的平台上运行,包括Win32,这将适用于Perl安装的任何地方。只需适当更改命令即可。

; } 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可能不可用),您可以使用它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 ”,它将立即终止并最终打印出测试。

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

tee命令可以在仍然传递数据的同时捕获管道中的stdout,并且 -a 使其附加到文件而不是每次都覆盖它。如果匹配, grep -q 返回0 ,否则 1 并且不向stdout写入任何内容。 $?是上一个命令的返回值,因此在这种情况下 $ CONT 将是grep的返回值。

执行此操作的简单方法是

until `/some/command`
do
  sleep 1
done

命令周围的反引号使直到测试一些输出被返回,而不是测试命令的退出值。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top