当使用两个管道时,读取循环似乎在第一行之后终止?

当使用两个管道时,读取循环似乎在第一行之后终止?
#!/usr/bin/env bash

set -euo pipefail

while read -r line
do
  echo "line via echo:"
  echo "$line"
  echo "line via sed:"
  sed 's/w/f/g' | sed 's/f/zzzzz/g' <<< "$line"
done < /dev/stdin

上面似乎只输出一行,我不知道为什么?

printf "123\n456\n789" | ./srScript.sh
line via echo:
123
line via sed:
123

它似乎是sed管道中的第二个,如果我删除它,它会按预期工作sed 's/w/f/g' |。但为什么会发生这种情况——这看起来很奇怪?

答案1

你的sed管道有点从后到前:

sed 's/w/f/g' | sed 's/f/zzzzz/g' <<< "$line"

这将导致第一个从标准输入(即您的和字符串sed)读取,而第二个将读取( )。该管道将​​阻止第一个管道的输出456789sed$line123sed任何地方因为第二个sed没有从中读取。

我假设你想要第一的 sed读取该行,而第二个sed读取第一个的输出。

你会这样做

{ sed 's/w/f/g' | sed 's/f/zzzzz/g'; } <<< "$line"

或者

sed 's/w/f/g' <<<"line" | sed 's/f/zzzzz/g'

另请注意,在这种情况下,您可以将两个sed调用合并为一个调用:

sed 'y/w/f/; s/f/zzzzz/g' <<<"$line"

或者,

sed -e 'y/w/f/' -e 's/f/zzzzz/g' <<<"$line"

我还更改了第一个表达式以使用y替换整行上的单个字符的命令。

然而,它是很少sed调用单独的输入行是个好主意。如果您不需要输出echo,您的脚本可以简化为

#!/bin/sh
sed 'y/w/f/; s/f/zzzzz/g'

甚至

#!/usr/bin/sed -f
y/w/f/
s/f/zzzzz/g

相关内容