管道中的命令如何中止管道?

管道中的命令如何中止管道?

鉴于管道

a | b | c

如果生成错误或匹配输入流中的特定模式,我该如何更改才能b中止管道?b

答案1

@mosvy非常有帮助回答曾是大多正确,但存在无论是否遇到“die”b()总是中止管道的问题:sed /die/q

输入流包含“die”

$ b(){ sed /die/q && kill "$BASHPID"; }; printf '%s\n' pass die oops | b | cat; echo "${PIPESTATUS[@]}"
pass
die
0 143 0

输入流才不是含有“死”字

$ b(){ sed /die/q && kill "$BASHPID"; }; printf '%s\n' pass oops | b | cat; echo "${PIPESTATUS[@]}"
pass
oops
0 143 0

在@mosvy的版本中,b()总是中止管道,因为sed /die/q如果遇到“die”,则返回退出代码0(成功)或者到达输入流的末尾,因此b()始终调用kill "$BASHPID".

在下面的版本中,我更正了@mosvy的答案,以便b()中止管道仅有的当它在输入流中遇到“die”时:

输入流包含“die”

b() {
  sed '/die/{q 2}' || kill "$BASHPID"
}

# Send "die" to b.
printf '%s\n' pass die oops | b | cat

echo "${PIPESTATUS[@]}"

输出:

pass
die
0 2 0

输入流才不是含有“死”字

b() {
  sed '/die/{q 2}' || kill "$BASHPID"
}

# Do not send "die" to b.
printf '%s\n' pass oops | b | cat

echo "${PIPESTATUS[@]}"

输出:

pass
oops
0 0 0

请注意,在此版本的 中b(),如果sed遇到“die”,它会调用q 2导致立即终止并退出代码 2(失败)的命令sed,然后||调用kill "$BASHPID"该命令终止b()管道中的进程并中止管道。 (注意这个版本需要GNUsed哪个扩展命令q以便它接受退出代码。)

正如 @mosvy 提到的,与其进行“仪式性自杀”,b()不如简单地exit从以下过程开始:

b() {
  sed '/die/{q 2}' || exit 3
}

# Send "die" to b.
printf '%s\n' pass die oops | b | cat

echo "${PIPESTATUS[@]}"

输出:

pass
die
0 3 0

相关内容