Mar*_* An 2 bash text-processing control-flow
我想执行commandA打印以下内容:
line1
line2
line3
started successfully
line4
...
...
Run Code Online (Sandbox Code Playgroud)
当打印该行时,started successfully我想启动另一个命令(并且可能多路复用它们的输出,以便两者都打印在终端上)。
我怎样才能在 bash 中实现这一目标?
您可以通过以下一种方法来做到这一点:
$ outputfile=output.log
$ commandA | tee "$outputfile" & tail --pid=$! -n+1 -f "$outputfile" |grep -q "started successfully" && commandB; wait
Run Code Online (Sandbox Code Playgroud)
tee命令将输出写入 STDOUT 和名为$outputfile.tail --pid=$! -n+1 -f "$outputfile"- 您运行tail命令$outputfile并从第一行开始跟踪其输出。
--pid=$!需要该标志来确保tail命令一旦commandA完成就终止。grep -q "started successfully"- 将在第一次出现所需字符串时成功(安静地)退出。&& commandB- 如果grep找到该字符串,它将执行commandB。
&&and not;来确保仅 当在 的输出中找到该字符串时才commandB执行。如果在未写入此字符串的情况下完成(例如,如果失败),则您不想运行第二个命令。commandAcommandAwait- 如果commandB之前完成,则在返回 shell 之前
commandA继续等待运行。commandAfg而不是wait让commandA继续在前台运行。commandB受到 @PaulPazderski 答案的启发,这是另一种无需日志文件和命令的方法tail:
$ commandA | tee >(grep -q "started successfully" && commandB; cat >/dev/null)
Run Code Online (Sandbox Code Playgroud)
唯一的缺点是,如果在之前commandA完成,shell 将在完成后立即返回到提示符,同时可能仍在后台运行,甚至将输出写入终端。 commandBcommandAcommandB
为了解决这个问题,只需将最终输出通过管道传输到另一个命令,例如cat,以确保只有当没有任何内容写入 stdout 时 shell 才会返回到提示符(这意味着整个命令已完成,甚至是commandB)。
$ commandA | tee >(grep -q "started successfully" && commandB; cat >/dev/null) | cat
Run Code Online (Sandbox Code Playgroud)