グループ化コマンドのPOSIX指定テールアクションですか?

グループ化コマンドのPOSIX指定テールアクションですか?

tail他の標準ツールと組み合わせて使用グループ化コマンドいくつかの強力な建物を建てることができます。たとえば、ファイルの最初の行と最後の行を取得するには、次のようにします。

$ seq 10 > file
$ { head -n1; tail -n1; } <file
1
10

パイプからグループコマンドでファイルの内容を入力すると、tailパイプは次のようになるため、出力を生成できません。連合国 -探す有能な:

$ seq 10 | { head -n1; tail -n1; }
1

コンテンツが十分に大きい場合は、tail次のように動作します。

$ seq 10000 | { head -n1; tail -n1; }
1
10000

lseek最初の失敗後はtail失敗ではないことを知っているからだ。検索可能これはファイル記述子であり、パイプの内容をまだ読み取っていないので、最後まで内容を読み始めます。

ユーザーの観点からは、入力サイズに関係なく動作が一貫したいと考えています。 POSIXのドキュメントを見ましたが、tail説明lseekが見つかりませんでした。

この動作はPOSIXで指定しますか?そうでなければ、どのように結果を一貫して作成できますか?


私はGNUテールとFreeBSDテールでテストしましたが、どちらも同じ動作をしています。

ベストアンサー1

問題はここにはありませんが、tailここでheadは出力したい最初の行よりもパイプからより多くの内容を読み込みます(したがって読む内容はありませんtail)。

はい、POSIXと互換性があります。

head入力を取得できる場合は、カーソルは出力の最後の行の直後にstdinに残る必要がありますが、そうでない場合はそうではありません。

http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html:

標準ユーティリティが検索可能な入力ファイルを読み取り、ファイルの終わりに到達する前にエラーなしで終了する場合、ユーティリティは、開かれたファイル記述のファイルオフセットがユーティリティが処理した最後のバイトの後に正しく配置されていることを確認する必要があります。検索できないファイルの場合、ファイルの開かれたファイル記述のファイルオフセット状態は指定されません。

head検索できないファイルでこれを実行できることは、一度に1バイトを読む必要があることを意味するため、非常に非効率的です。これは、ユーティリティまたはGNUがreadこのオプションを使用して実行する操作です。linesed-u

したがって、この動作が必要な場合に置き換えるhead -n 20ことができます。gsed -u 20q

ここでは、次のようになります。

sed -e 1b -e '$b' -e d

代わりに。ここでは1つのツール呼び出ししかないため、2つのツール呼び出し間で内部バッファを共有できないという問題はありません。ただし、大容量ファイルの場合はsedファイル全体を読み取る方が効率が悪く、検索可能なファイルの場合はtailほとんどのファイルをスキップします。救うファイルの末尾に近い。

バッファリングに関する関連議論を参照してください。シェルループを使用してテキストを処理するのはなぜ悪い習慣と見なされますか?

tailストリームの尾は標準入力として出力する必要があります。最適化された検索可能なファイルとして、実装はファイルの終わりに移動してそこから末尾のデータを取得できますが、呼び出し時に最初の場所の前のポイントに戻ることはできませんtail(Busyboxはtail以前このバグを持っています)。

たとえば、

{ cat; tail -n 1; } < file

tail最後の行に戻ることはできますが、そうではfileありません。標準入力は、catファイルの末尾にカーソルがある空のストリームです。ファイルをさらに詳しく見ると、このストリームからデータを回復できません。

(上記のテキストは確認のために行を描きました。公開グループの説明複数の実装が正しく行われていないことを考慮してください。)


1ソケット(探索できないファイル)の組み込みhead機能(ksh93前に置くと有効)/opt/ast/bin$PATH現れるrecvfrom(..., MSG_PEEK)実際の入力前(使用)読むあまり読まないようにするには、どれくらい読むべきかを確認してください。他のファイル形式の場合は、一度に1バイトずつ読み取ることで置き換えられます。これはやや効率的です。これがsocketpair()Pipes を実装するのではなく s を使う主な理由だと思いますpipe()。他のプロセスがソケット間でデータを読み取ると、競合状態が発生する可能性があるため、これは完全に安全ではありません。現れるそして読む

おすすめ記事