シェル関数。これは、<<<
をサポートするすべてのシェルで機能します。 zsh と bash を含む here-strings。
xyz() {
while read line
do
printf "%s " "$line"
"[email protected]" <<<"$line"
done
}
$ (echo "foo"; echo "bar") | xyz rev
foo oof
bar rab
ほとんどの場合、stdio バッファリングの動作方法が原因で、多くの問題が発生します。 Linux での回避策は、stdbuf
を使用することです。 プログラムを作成し、coproc を使用してコマンドを実行すると、出力のインターリーブを明示的に制御できます。
以下は、コマンドが入力の各行の後に 1 行を出力することを前提としています。
#!/bin/bash
coproc stdbuf -i0 -o0 "[email protected]"
IFS=
while read -r in ; do
printf "%s " "$in"
printf "%s\n" "$in" >&${COPROC[1]}
read -r out <&${COPROC[0]}
printf "%s\n" "$out"
done
OPがプログラムへの入力の各行のみを最終的にする必要があるため、より一般的な解決策が必要な場合 すぐにではなく 1 行を出力する場合は、より複雑なアプローチが必要です。 read -t 0
を使用してイベント ループを作成します。 標準入力とコプロセスから読み取りを試みます。両方に同じ「行番号」がある場合は出力し、そうでない場合は行を保存します。イベント ループのいずれかのラウンドでどちらも準備ができていない場合に CPU の 100% を使用しないようにするには、イベント ループを再度実行する前に少し遅延を導入します。プロセスが部分的な行を出力する場合、さらに複雑になります。これらはバッファリングする必要があります。
このより一般的な解決策が必要な場合は、expect を使用してこれを記述します。これは、複数の入力ストリームでのパターン マッチングの処理が既に適切にサポートされているためです。ただし、これは bash/zsh ソリューションではありません。
この特定のケースでは、 perl
を使用します :
printf '%s\n' foo bar | perl -Mopen=locale -lpe '$_ .= " " . reverse$_'
foo oof
bar rab
書記素クラスターでも動作するように拡張できます:
$ printf '%s\n' $'complique\u301' |
perl -Mopen=locale -lpe '$_ .= " " . join "", reverse/\X/g'
compliqué éuqilpmoc
または zsh
:
while IFS= read -r line; do
print -r -- $line ${(j::)${(s::Oa)line}}
done
while read
の使用は避けたいと思いますが、 zsh
であっても、テキストを処理するためのループ (この特定のケースでは、組み込みコマンドしか使用されていないため、それほど悪くはありません)。
一般的には、一時ファイルを使用するのがおそらく最善の方法です。 zsh
で 、あなたはそれを行うことができます:
(){paste -d ' ' $1 <(rev <$1)} =(print -l foo bar)
(ここで =(...)
一時ファイルの作成とクリーンアップを処理します)。
パイプと何らかの形式の tee
に置き換える ing は、一般的なケースでのデッドロックのレシピです。デッドロック状況に関するいくつかのアプローチと詳細については、次の同様の質問を参照してください。
- 別のコマンドの入力を分割し、結果を結合する
- tee + cat:出力を数回使用し、結果を連結します