Ubuntuで名前付きパイプを試してみましたが、以前に使ったことはありません。私は次のことをしました。
mkfifo pipe
ls>pipe&
cat pipe
これにより、マイフォルダにあるすべてのファイルのリストがpipe
表示されます。一度にパイプの2行を読み取ろうとします。だから、一度実行すると、フォルダの最初のファイルと2番目のファイルの名前を提供するコマンドが必要です。コマンドを再実行すると、3番目と4番目のファイル名が必要です。これを行う方法はありますか?
私は努力したhead -2 pipe
。最初の2つのファイル名が表示されます。しかし、もう一度実行すると停止します。前進する正しい方法は何ですか?
答え1
読み取り側でFIFOを開いたままにしたい。 1つの方法は、bashに開かれたファイル記述子を保持させることです。
#!/bin/bash
mkfifo pipe
ls > pipe &
exec 8< pipe
r2(){
read -ru 8 fn1
read -ru 8 fn2
echo "$fn1" "$fn2"
}
r2 # print out first 2 files
sleep 1 # do something
r2 # print out next 2 files.
答え2
2行だけを読み込み、もう読み取らないコマンドが必要です。
入力がパイプでないときにこれを行う機能閲覧可能、コマンドには3つのオプションがあります。
- 2 番目の改行文字が見つかるまで一度に 1 バイトずつ読みます。
- パイプの内容を(使用せずに)見て、2番目の改行文字がどこにあるかを確認し、一度にできるだけ多くのデータを読み取ります。
- ブロックの入力を読みます。ただし、2行以上を読んだ場合は、余分な部分をパイプに戻してください。
read()
1はバイトごとに1つのシステムコールしかないため、多くのシステムで高価です。 2 と 3 は、すべてのシステムでパイプを調査したり、パイプにデータを書き戻すことをサポートしていないため、すべてのシステムで動作するわけではなく、複数のプロセスが同時にパイプから読み取ると信頼できません。
したがって、一般的に言えば、いくつかの例外を除いて、コマンドは読み取りに干渉しません。正確に入力内容を検索できない場合は、行数を知らせます。
ほとんどの実装では、入力の最初の2行をhead
出力しますが、より多くの入力を消費できます。head -n2
注目すべき例外の1つは、head
ksh93シェルの組み込み関数で、可能であることを確認して一度に1バイトずつ読み込む機能です。
一部のコマンドは、処理する最後の行以上を読み取らないように指示できます。
GNUの場合、sed
オプションは次のとおりです-u
。
sed -u 2q
2行(一度に1バイト)を読むと、それがすべてです。
このline
ユーティリティ(標準のユーティリティではなく、現在は常に見つかりません)は、1行だけを読むユーティリティです。
内蔵機能は1行以上を読み取ることがread
できません。sh
したがって、line
上記のコマンドは次の方法で実装できます。
IFS= read -r line; printf '%s\n' "$line"
(入力行が終わらなくても改行を追加することに注意してください)。
(POSIXはline
によって達成することができるので実際に削除を正当化しますread
)。
line
追加の改行を追加せずにeofからfalseを返す実装の場合。
line() {
if IFS= read -r line; then
printf '%s\n' "$line"
else
printf %s "$line"
false
fi
}
そしてtwolines
ちょうど:
twolines() { line && line; }
これにより、次のことができます。
mkfifo pipe
ls > pipe &
while
echo next two lines:
twolines
do
continue
done < pipe