私はinとoutをCtrl+D使って読むと、私の変数にテキスト転送文字(EOT、ASCIIコード4)が終わる理由を見つけようとしました。read -N 1
bash
ksh93
私は転送終了文字とファイル終了条件の違いを知っており、使用しないときに何が起こるのかをCtrl+D知っread
ています-N
(EOTを送信し、入力が空の場合はデフォルトの戻り値が0になり、read()
EOF信号を送信します)。
しかし、特定の数の文字を読み取ろうとすると、これらの動作がなぜそんなに大きく変わるのかは分かりません。 EOF条件が発生し、次のループが終了すると予想しました。
while read -N 1 ch; do
printf '%s' "$ch" | od
done
押すと出力Ctrl+D:
0000000 000004 0000001
ドキュメントには次のようにbash
記載されていますread -N
(ksh93
同様のフレーズを含む)。
-N nchars
nchars
;完全な入力行を待たずに文字を正確に読み取った後に返されます。EOFに会わない限りまたは読み取りがタイムアウトしました。
...しかし、TTYをraw / bufferedモードに切り替えることについては言及しません(私の考えでは何が起こっているのか)。
オプションはと同じように動作する-n
ように見え、読み取る文字も重要ではないようです。read
Ctrl+D
入力の終わりを通知してread -N
ループを終了するにはどうすればよいですか(読み取り値をテストすることに加えて)、これが「裸」と異なるのはなぜですか?read
?
答え1
文書にASCII EOFのようなものがなく、^ DのASCIIセマンティクスがEOTと指定されている場合は、さらに役立つ可能性があります。これは、ターミナルドライバが標準モードで提供するものです。現在の送信者read
.programを終了します。説明するゼロの長さはファイル内のEOFのように見えるため、EOFに読み込まれますが、ターミナルドライバは文字コード4の提供を拒否し、代わりにそれを飲み込んで常に望ましくない読み取りを終了します。
これがここで起こるものです。制御文字セマンティクスは標準モードの一部です。ここで、ターミナルドライバは、ルールに特別な意味を割り当てる文字が表示されるまでバッファリングします。これはEOT、BS、CR、および他の多くの場合に当てはまります(すべての詳細を見て学ぶ)stty -a
。man termios
read -N
次のN文字のみを渡す明示的なコマンド。これを行うには、シェルはターミナルドライバに標準的な意味を求めるのをやめる必要があります。
ところで、EOFは実際に端末が設定または入力できる条件ではない。
他のものについてeofを読み続けると、EOFインジケータは引き続き表示されますが、端末ドライバが提供できる唯一のEOFは偽のEOFです。考えてみてください。端末ドライバが実際に実際のEOFを提供している場合、シェルは読み続けることができません。すべて同じ端末です。ここで:
#include <unistd.h>
#include <stdio.h>
char s[32];
int main(int c, char**v)
{
do {
c=read(0,s,sizeof s);
printf("%d,%.*s\n",c,c,s);
} while (c>=0);
}
端末で試してみると、標準モードの端末ドライバはEOTを解釈して未解決の読み取りを完了し、読み取りバッファリングに関係なく標準入力終端が現れるまで内部的にバッファリングすることがわかります。 32バイトより長い)。
あなたを混乱させるテキスト
EOFに会わない限り
実際のEOFを表します。