BashでEOFを可視化する方法

BashでEOFを可視化する方法

/dev/null作成されたすべてのコンテンツを削除してEOF読み取るために使用できる特別なLinuxファイル。

/dev/null私はこれを読書を通して得て視覚化したいと思いましたEOF。私が試した場合:

$ cat /dev/null | hexdump

これはうまくいきません。出力なしでプロンプトに戻ります。EOFASCIIコードでさえないので、そうかもしれません。

  1. それでもEOFキャラクターだと見ることができますか?

  2. EOFBashで提供されている場合、それを検出して印刷する方法はありますかstdin

それは次のとおりです。

$ cat /dev/null | some_tool
EOF

私はUbuntu 20.04.3を使用していますが、解決GNU bash, version 5.0.17(1)-release (x86_64-pc-linux-gnu)策がある場合は、これらの特定のバージョンとは無関係であることを願っています。


これはいいえ宿題ですが、もっと学ぶ方法ですEOF

答え1

元のASCII制御文字セットで定義された一連の「{something}末尾」文字がありますが、EOFは文字ではありません。 EOF は、入力ストリームから読み取れなくなったため、検出可能な条件です。

たとえば、このループは読み取る内容がなくなるまで(つまり、EOFに達するまで)続きます。

{
  while IFS= read -r line; do
    printf '%s\n' "Read: >> $line <<"
  done
  if [ -n "$line" ]; then
    printf '%s\n' "And some extra data after the last line: >> $line <<"
  fi
  echo 'No more'
}

または、より効率的に(一部の実装ではNULバイトをブロックしないsed)、シェルループを完全に避けてください。

LC_ALL=C sed 's/.*/Read: >> & <</'; echo 'No more'

(最後の行の後にデータがある場合は、No moreその行の接頭辞として使用します。)

端末のデフォルト設定は、キーを^D押すと端末から送信された文字がCtrl D端末ドライバによってEOFを表すと解釈されることです。ただし、その文字(または他の文字)はアプリケーションに送信されません。 tty デバイスファイルの s が読み取る内容を返すようにし、read()何もなければアプリケーションはそれを EOF と解釈します。端末装置の現在のEOF文字)。独自の行エディタを実装するシェルまたは他のアプリケーションは通常、この文字を同じ方法で処理します(少なくとも空行バッファにある場合)。stty -aeof

答え2

取得できるの/dev/nullは、read()システムコールが正常に返され、ゼロバイトが読み取られるということです。これは、ファイルの終わりから(またはそれ以降)起動しようとしたときに発生するのと同じであるため、read()「ファイルの終わり」と呼ばれます。

ただし、端末のように1回の呼び出しでゼロバイトを返すことができます(ユーザーが空の行をクリックするか、^D別の呼び出しの後に^D)、次の読み取りでより多くのデータを返す奇妙な場合があります。 0バイトのデータグラムをサポートできるデータグラムソケットもあり、システムはこれらのデータグラムに対して0バイトを返しますが、次の呼び出しではまだ次のデータグラムを返します。もちろん、read()最後にファイルから0バイトを取得することもできますが、後でもう一度呼び出しようとすると、今回はより多くのデータが待機していることがわかります。 (これはtail -f実装が実行できるタスクです。)

印刷するものがないため、実際に「EOFを印刷」することはできません。ただデータが足りないだけです。

EOFでの終了を知っていれば、cat確かに次のことができます。

(cat /dev/null; echo EOF) | whatever...

完了したら、何かを印刷します。私の考えでは、これはあまり役に立ちません。

望むより:

答え3

/dev/null送らないでくださいEOF。ただ接続が切断されます。ファイルを閉じます。長さ0のファイルをエミュレートします。

答え4

論理的には、EOFの概念はI / Oハンドラによって生成されます。 EOF信号は一般に処理されるデータとは関係がない。

「EOFを送信する」唯一の方法は、読者に何かを読んでもらうという要求に応じて読むことがないと報告することです。

Hi関数がEOFまでstdinを中継し、echoコマンドの出力を再生するために使用される次のコードを考えてみましょう。

Hi() {
  while IFS= read -r -d $'\n' || [[ "$REPLY" ]]; do
    echo "Hi: $REPLY"
 done }
Hi < <(echo Hello)
Hi: Hello
  • <(コマンド)は、bashが提供されたコマンドの出力に基づいてパイプ(概念的にファイル)を生成するようにします。
  • <(コマンド)は、次のように言うとパイプの一意のファイル名に置き換えられます。
echo <(echo Hi)
/dev/fd/63

したがって、<(コマンド)はstdoutからファイルを生成し、各ファイルにはデータの物理的な終わりのために利用可能なデータがないことをリーダーが知ることができる論理EOFがあるかもしれません。

<()内の命令が継続して実行されている間、パイプは開いたままであるため、パイプは開いたままである。 <(コマンド)が完了すると、パイプの入力端が閉じます。

bash read文がEOFを検出すると、エラーコード1で終了します。 ilkkachuによると、これはファイルから読み取られるデータがなくなったときに発生するため、成功したゼロバイトシステムのread()です。

ファイルリーダーがアクティブプロセスのままである限り、システムのread()呼び出しは返されずに中断される可能性があります。タイムアウトにより永久に中断されるのを防ぎます。物理ドライブの起動やその他の接続が非常に遅くなる可能性があります。タイムアウトのためにEOFを仮定するのは遅く、エラーが発生しやすい。成功したシステム読み取り()0バイト= EOF。

while IFS= read -r -d $'\n' || [[ "$REPLY" ]]; do

||(論理OR)テストは、ファイルがキャリッジリターンで終わらない場合を処理するために存在します。 -d によると、キャリッジリターンを読み取ると bash read が正常に返されます。データが正常に読み込まれたとしても、Bash の読み取りはゼロ以外のコード 1 で失敗するため、コード 1 で失敗します。これはbashがリレーEOFを読み取る方法です。

入力から出力に情報を渡すすべてのプログラムは、データ・ストリームで表示される情報に応答するように選択できます。

コンソールtty(現在のptyまたは擬似端末)ラインリーダー/エディター(ReadLine)は、キーボードから読み取られた複数の文字とエスケープシーケンスに応答して特別な意味を与えます。たとえば、Control-Hはバックスペースを実行し、Control-DはEOF信号(EOTまたは転送終了と呼ばれる)を送信し、tty自体は開いたままにして他の読み取りに関する追加情報を送信できます。

関連情報