找到匹配时让grep提前退出

时间:2014-11-06 10:36:47

标签: bash grep

我在bash中有以下行。

(sleep 1 ; echo "foo" ; sleep 1 ; echo "bar" ; sleep 30) | nc localhost 2222 \
| grep -m1 "baz"

这打印" baz" (如果/当TCP连接的另一端发送它时)并在32秒后退出。

我想要它做的是提前退出sleep 30 如果它看到" baz"。 -m标志退出grep,但不会终止整行。

我怎样才能在bash中实现这一点(如果可能的话,不使用expect)?


更新:当且仅当服务器尝试在baz之后发送内容时,上面的代码才会退出。这并不能解决这个问题,因为服务器可能几分钟都没有发送任何内容。

4 个答案:

答案 0 :(得分:3)

你可以抓住你正在打开的子壳的pid。然后,这样的事情应该:

( echo "start"; sleep 1; echo $BASHPID > /tmp/subpid; echo "hello"; sleep 20; ) \
  | ( sleep 1; subpid=$(cat /tmp/subpid); grep -m1 hello && kill $subpid )

也就是说,将子shell的id存储在临时文件中,然后继续描述。

在管道的另一端,您读取文件的内容(sleep 1以确保它已由初始子shell写入文件中),并且当您找到带有{{{1}的内容时1}},你杀了它。


来自grep

  

BASHPID

     

扩展为当前bash进程的进程ID。这有所不同   在某些情况下来自$$,例如没有的子壳   要求重新初始化bash。

致记:

答案 1 :(得分:3)

如果您喜欢Bash的深奥,可以使用coproc

coproc { { sleep 1; echo "foo"; sleep 1; echo "bar"; sleep 30; } | nc localhost 2222; }
grep -m1 baz <&${COPROC[0]}
[[ $COPROC_PID ]] && kill $COPROC_PID

在这里,我们正在使用coproc来运行

{ { sleep 1; echo "foo"; sleep 1; echo "bar"; sleep 30; } | nc localhost 2222; }

在后台。 coproc注意在${COPROC[0]}${COPROC[1]}中设置的文件描述符中重定向此复合命令的标准输出和标准输入。此外,此作业的PID位于COPROC_PID。然后,我们使用后台作业的标准输出提供grep。当我们完成工作时,很容易就能完成工作。

答案 2 :(得分:1)

突然根据Jidder的评论找到了解决方案。

(sleep 1 ; echo "foo" ; sleep 1 ; echo "bar" ; for i in `seq 1 30`; do echo -n '.'; sleep 1; done) | grep -m1 "bar"

只是在循环中睡觉不起作用。但是在添加echo -n '.'之后它才有效。似乎写入封闭管道的尝试导致中止。虽然我已经测试过没有nc。

答案 3 :(得分:1)

我相信你真的需要使用expecthttp://expect.sourceforge.net/,并且有适用于大多数操作系统和发行版的软件包。)

否则你将很难处理某些案例并摆脱缓冲等等。期待它适合你(......好吧,一旦你写了正确的脚本,除了处理所有(或大多数)案件的脚本)(对于初稿,您可以使用autoexpect(http://linux.die.net/man/1/autoexpect),但您需要添加变体(处理&#34;错误的密码&#34;消息等))

Expect是一个老工具(并且基于,iirc,基于Tcl),但实际上并没有最好的工具来发送输入和等待输出(并根据输出做出不同反应)& #34;