微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

我敢肯定,perl,ruby,bash有一些简单的一行,不pipe是什么让我在循环中运行一个命令,直到我在stdout中观察到一些string,然后停止。 理想情况下,我也想捕获stdout,但是如果要安装,那可能就足够了。

目前有问题的特定环境是RedHat Linux,但有时候在Mac上也需要同样的东西。 所以,通用和* nixy将是最好的。 不关心Windows – 据推测,一个* nixy的东西可以在cygwin下运行。

更新:请注意,通过“观察一些string”我的意思是“标准输出包含一些string”而不是“标准输出是一些string”。

如何在执行shell脚本时closuresecho

在Linux中获得硬盘的自由空间

从python脚本导入shellvariables

使用shell脚本从文件提取独特的行块

从OpenSSH客户端删除字符

将手册页输出redirect到文件结果用双字母表示

运行期望代码时发送错误

使用bash:将整数的位表示写入文件

把JSONstring变成variables

在sh中初始化数组

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

免责声明:只有轻度测试,可能需要做一些额外的转义等,如果你的命令有很多的参数或字符串包含特殊的字符。

编辑 :根据亚当的评论反馈 – 如果你不需要任何原因的输出(即不想显示输出),那么你可以使用这个较短的版本,反引号的使用较少,因此较少的开销:

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); $_ = `command`; print $_; } until (m/search/);'

对于像这样的东西,Perl是一个非常好的语言。 用你想要反复运行的命令替换“command”。 将“搜索”替换为您要搜索内容。 如果你想搜索一些斜线,那么把m/search/替换成m#search字符串。

另外,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不会输出任何内容到标准输出),但是如果你使用“ echo test ”,它会立即终止并打印出测试结果。

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

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

一个简单的方法来做到这一点将是

until `/some/command` do sleep 1 done

命令周围的反引号使until测试某个输出被返回,而不是测试命令的退出值。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。

相关推荐