#!/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
これはパイプラインの2番目に見え、それを削除すると期待どおりに機能しますsed 's/w/f/g' |
。しかし、なぜこれが起こるのですか?変なんですか?
答え1
パイプsed
ラインはやや後ろから前方に移動します。
sed 's/w/f/g' | sed 's/f/zzzzz/g' <<< "$line"
これにより、最初の入力は標準入力(つまりyourとstring)から読み取られ、sed
2番目の入力は()を読み取ります。このパイプは最初のパイプの出力をブロックします。456
789
sed
$line
123
sed
どこかに二つ目はsed
読まないからです。
私はあなたが欲しいと思います。最初 sed
2行目はsed
1行目の出力を読み込みます。
あなたはこれを行います
{ sed 's/w/f/g' | sed 's/f/zzzzz/g'; } <<< "$line"
または
sed 's/w/f/g' <<<"line" | sed 's/f/zzzzz/g'
また、この場合、両方のsed
呼び出しを1つにまとめることができます。
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