代码之家  ›  专栏  ›  技术社区  ›  Alex Miller

如何在循环中运行命令,直到在stdout中看到一些字符串?

  •  14
  • Alex Miller  · 技术社区  · 16 年前

    我确信perl、ruby、bash都有一些简单的一行程序,可以让我在循环中运行命令,直到我在stdout中观察到一些字符串,然后停止。理想情况下,我也希望捕获stdout,但如果它要用于控制台,那就足够了。

    更新:注意,“观察一些字符串”的意思是“stdout包含一些字符串”,而不是“stdout是一些字符串”。

    8 回复  |  直到 16 年前
        1
  •  13
  •   Derek Park    16 年前

    在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~
    

    不过,您可能需要在其中添加睡眠。

        2
  •  11
  •   Jay    16 年前

    有很多方法可以做到这一点,首先想到的是:

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

    其中$cmd是要执行的命令。

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

    免责声明:仅经过轻微测试,如果您的命令有大量参数或字符串包含特殊字符,则可能需要执行一些额外的转义等操作。

    编辑 不要

    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
    }
    
        3
  •  7
  •   Arnab Nandy    9 年前

    我很惊讶我没有看到这里提到的一个简短的Perl one liner:

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

    Perl对于这样的东西来说是一种非常好的语言。将“命令”替换为要重复运行的命令。将“搜索”替换为您要搜索的内容。如果要搜索带有斜杠的内容,请替换 m/search/ 具有 m#search 串连 /es#

    此外,Perl运行在许多不同的平台上,包括Win32,无论您在哪里安装Perl,这都可以运行。只要适当地更改您的命令即可。

        4
  •  6
  •   ordnungswidrig    16 年前

    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
    

    …这将打印一些漂亮的点来表示进度。

        5
  •  1
  •   zigdon    16 年前
    while (/bin/true); do
      OUTPUT=`/some/command`
      if [[ "x$OUTPUT" != "x" ]]; then
        echo $OUTPUT
        break
      fi
    
      sleep 1
    done
    
        6
  •  1
  •   Mecki    16 年前

    我最初的回答是假设“某个字符串”意味着“任何字符串”。如果您需要寻找一个特定的正则表达式,Perl可能是您最好的选择,因为在正则表达式匹配方面几乎没有什么能比Perl更好。

    但是,如果您出于任何原因不能使用Perl(您可以期望Perl出现在大多数Linux发行版中,但是没有人强迫用户安装它,尽管Perl可能不可用),那么您可以在grep的帮助下进行安装。然而,到目前为止,我看到的一些grep解决方案是次优的(它们比必要的慢)。在这种情况下,我宁愿做以下工作:

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

    代替 使用实际运行的命令 几根绳子 使用要搜索的字符串。如果在命令的输出中找到某个_字符串,循环将停止并打印找到某个_字符串的输出。

    原始答复:

    可能不是最好的解决方案(我不是一个优秀的bash程序员),但它会起作用:-P

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

    只需将XXXX替换为您的命令调用,例如,尝试使用“ 回响 而且它将永远不会返回(因为echo从不将任何内容打印到标准输出),但是如果您使用 回声测试

        7
  •  1
  •   Arnab Nandy    9 年前
    CONT=1; while [ $CONT -gt 0 ]; do $CMD | tee -a $FILE | grep -q $REGEXP; CONT=$? ; done
    

    tee命令可以捕获管道中的stdout,同时仍在上传递数据,并且 -a grep -q return 0 如果有一场比赛, 1 否则,不向标准输出写入任何内容。 $? 是上一个命令的返回值,因此 $CONT 将是本例中grep的返回值。

        8
  •  0
  •   David Webb    16 年前

    until `/some/command`
    do
      sleep 1
    done
    

    命令周围的反勾号使 until