ヘッドスクリプト出力の説明

ヘッドスクリプト出力の説明

したがって、このシェルスクリプトは次のようになります。

#!/bin/bash
head >/dev/null;
head;

シーケンス番号(例:seq 10000 | ./sscript)を使用して呼び出すと、ほぼ常に同じ出力が得られます。

出力:

     //blank line
1861
1862
1863
1864
1865
1866
1867
1868
1869

私はそれを追跡しましたが、strace seq 10000 | ./sscriptこの数字が正確にどこから来たのかを自分で説明することはできませんでした。 straceが終わったら:

write(1, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 4096) = 4096
write(1, "1\n1042\n1043\n1044\n1045\n1046\n1047\n"..., 4096) = 4096
write(1, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 4096) = 4096
write(1, "2680\n2681\n2682\n2683\n2684\n2685\n26"..., 4096) = 4096
write(1, "499\n3500\n3501\n3502\n3503\n3504\n350"..., 4096) = 4096
write(1, "18\n4319\n4320\n4321\n4322\n4323\n4324"..., 4096) = 4096
write(1, "7\n5138\n5139\n5140\n5141\n5142\n5143\n"..., 4096) = 4096
write(1, "\n5957\n5958\n5959\n5960\n5961\n5962\n5"..., 4096) = 4096
write(1, "6776\n6777\n6778\n6779\n6780\n6781\n67"..., 4096) = 4096
write(1, "595\n7596\n7597\n7598\n7599\n7600\n760"..., 4096) = 4096
write(1, "14\n8415\n8416\n8417\n8418\n8419\n8420"..., 4096) = 4096
write(1, "3\n9234\n9235\n9236\n9237\n9238\n9239\n"..., 3838) = 3838

write3番目のアイテムのみが返されるのはなぜですか(場合によっては2番目のアイテムのみが返されます)。

実際には、スクリプトの2行目のため、戻り行の最初の10行(3番目または2番目の書き込み)のみが印刷されますが、それでもhead失われます。

ベストアンサー1

headデフォルトでは10行を印刷しますが、これはできるだけ多くの入力を読み込みます。 GNUには、headファイルに何行が含まれているのかを知る必要があるいくつかのオプションがあります。できるだけたくさん。

head8192バイトに見えるバッファを埋めるために、できるだけ読み込みます。

~ seq 10000 | strace -fe read ./foo.sh
read(3, "\177ELF\2\1\1\0\0\0\0\0\0\0\0\0\3\0>\0\1\0\0\0\260e\1\0\0\0\0\0"..., 832) = 832
...
Process 17610 attached
...
[pid 17610] read(0, "1\n2\n3\n4\n5\n6\n7\n8\n9\n10\n11\n12\n13\n14"..., 8192) = 8192
...
[pid 17611] read(0, "\n1861\n1862\n1863\n1864\n1865\n1866\n1"..., 8192) = 8192
...

最初の2つの書き込みはそれぞれ4096バイトなので、最初の書き込みで使用できますhead

タイミングによって異なります。最初のアイテムが10行を印刷して終了したときに1つが正常に削除されると、2番目のアイテムはseq2番目のアイテムによって削除されます。writeheadwritehead

これMike Selfのコメント非常に啓発的です:

一般的なファイルを試してみてください。

seq 10000 >/tmp/nums; yourscript </tmp/nums

期待どおりに動作する理由は、head出力を使用して現在の読み取りポイントを読み取りポイントの次の行に再配置しようとするためです。lseek()。これは通常のファイル、リダイレクトされたファイルなどには機能しますが、パイプには機能しません。

The lseek() function shall fail if:

...

ESPIPE The fildes argument is associated with a pipe, FIFO, or socket.

これは以下を使用して見ることができますstrace

~ seq 10000 | strace -fe lseek ./foo.sh
...
Process 18561 attached
[pid 18561] lseek(0, -8171, SEEK_CUR)   = -1 ESPIPE (Illegal seek)
[pid 18561] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED, si_pid=18561, si_uid=1000, si_status=0, si_utime=0, si_stime=0} ---
Process 18562 attached
[pid 18562] lseek(0, -8146, SEEK_CUR)   = -1 ESPIPE (Illegal seek)
...

おすすめ記事