EnterキーがEOLを送信しないのはなぜですか?

EnterキーがEOLを送信しないのはなぜですか?

Unix/Linux EOL は、LF、改行、ASCII 10、エスケープシーケンスです\n

以下は、正確に1回のキーを押すためのPythonコードの断片です。

import sys, tty, termios
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
    tty.setraw(sys.stdin.fileno())
    ch = sys.stdin.read(1)
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

Enterこのコードフラグメントに応答してキーボードを押すと、\rキャリッジリターン、ASCII 13が表示されます。

存在するWindowsEnter送信CR LF == 13 10。 *nixはWindowsではありません。なぜEnter10ではなく13を提供するのですか?

答え1

本質的に「手動打者が出現して以来、そうなってきたからです」本当。

手動タイプライター輸送給紙されて給紙されたときに前方に移動し(スプリングが装着されている)、キャリッジを解除するレバーまたはキーがあり、スプリングがキャリッジを左マージンに戻すことができます。

電子データ入力(全身タイプライターなど)が導入され、彼らもこれを推進しました。このため、Enter多くの端末のキーにはというラベルが付いていますReturn

キャリッジを左マージンに戻した後、改行が発生します(手動プロセス中)。繰り返しますが、電子デバイスは、個々のline-feed操作のために受動デバイスを模倣する。

どちらの操作もCR(キャリッジリターン)とLF(改行)があります。この写真はASR 33テレタイプ情報キーボードをReturn右、Line-Feed左に表示します。それに正しい、これは主キーです。

ここに画像の説明を入力してください。

その後、Unixが登場しました。開発者は内容を短くするのが好きです(「生成された」すべての略語を見てくださいcreat)。潜在的に2つの部分からなるプロセスに直面して、彼らは改行文字の前にキャリッジリターンがある場合にのみ意味があると決定しました。だから彼らは明示的なキャリッジリターン文字を削除しました。文書、端末のReturnキーストロークを変換して対応する改行を送信します。混乱を避けるために、改行を「改行」といいます。

端末にテキストを書き込むと、Unixは逆変換を行います。改行はキャリッジリターン/改行になります。

(例:「一般」:翻訳を行わない「生」モードとは反対のいわゆる「料理モード」)。

要約:

  • キャリッジリターン/ラインフィードの順序は13 10です。
  • これ装備13個送ってください(あなたの言葉は「永遠」だから)
  • Unixシリーズシステム変化13 10 まで
  • 他のシステムは必ずしも10個しか保存する必要はありません(Windowsは基本的に互換性がどれほど重要かによって10または13 10のみを許可します)。

答え2

しかし、トーマスディキの答えそうですね。 Stéphane Chazelasは、Dickeyの回答についてのコメントで転換が確定したのではなく、ライン規律の一部であると正しく言及しました。

実際、翻訳は完全にプログラム可能です。

これ男3用語マニュアルページには、基本的にすべての関連情報が含まれています。 (このリンクではLinuxのマニュアルページプロジェクト、Linuxのみの機能、およびPOSIXまたは他のシステムに共通の機能を常に確認してください。遵守する各ページのセクション。 )

端末iflag属性(old_settings[0]質問に表示されているコードからPython)には、すべてのPOSIXyシステムに3つの関連フラグがあります。

  • INLCR:設定されている場合、入力時にNLをCRに変換します。
  • ICRNL:設定した場合(IGNCR設定しない場合)、入力時にCRをNLに変換します。
  • IGNCR:入力時CRを無視

同様に、関連する出力設定()がありますold_settings[1]

  • OPOST:出力処理を有効にします。
  • OCRNL:出力からCRをNLにマップします。
  • ONLCR:出力からNLをCRにマップします。 (XSI; すべての POSIX または単一の Unix 仕様システムには適用されません。)
  • ONOCR:最初の列のCRをスキップします(出力しません)。
  • ONLRET:CRをスキップします(出力しません)。

たとえば、このttyモジュールに依存しない可能性があります。 「makeraw」操作は単にフラグセット(およびoflagセットCS8)を消去します。

import sys
import termios

fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
ch = None

try:
    new_settings = termios.tcgetattr(fd)
    new_settings[0] = new_settings[0] & ~termios.IGNBRK
    new_settings[0] = new_settings[0] & ~termios.BRKINT
    new_settings[0] = new_settings[0] & ~termios.PARMRK
    new_settings[0] = new_settings[0] & ~termios.ISTRIP
    new_settings[0] = new_settings[0] & ~termios.INLCR
    new_settings[0] = new_settings[0] & ~termios.IGNCR
    new_settings[0] = new_settings[0] & ~termios.ICRNL
    new_settings[0] = new_settings[0] & ~termios.IXON
    new_settings[1] = new_settings[1] & ~termios.OPOST
    new_settings[2] = new_settings[2] & ~termios.CSIZE
    new_settings[2] = new_settings[2] | termios.CS8
    new_settings[2] = new_settings[2] & ~termios.PARENB
    new_settings[3] = new_settings[3] & ~termios.ECHO
    new_settings[3] = new_settings[3] & ~termios.ECHONL
    new_settings[3] = new_settings[3] & ~termios.ICANON
    new_settings[3] = new_settings[3] & ~termios.ISIG
    new_settings[3] = new_settings[3] & ~termios.IEXTEN
    termios.tcsetattr(fd, termios.TCSANOW, new_settings)
finally:
    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)

return ch

互換性のために、まずこれらすべての定数がtermiosモジュールに存在することを確認したい場合があります(POSIX以外のシステムで実行されている場合)。処理するデータがない場合に読み取りをブロックするかどうか、およびブロック期間(10秒単位の整数)を設定するには、およびを使用することnew_settings[6][termios.VMIN]もできます。new_settings[6][termios.VTIME](読み取りをすぐに返す必要がある場合は、通常VMINゼロに設定されるか、VTIME読み取りが最大待機する時間の正数(10分の1秒)に設定されます。)

ご覧のとおり、上記(および通常「makeraw」)は入力へのすべての翻訳を無効にします。これは猫が見ている動作を説明します。

    new_settings[0] = new_settings[0] & ~termios.INLCR
    new_settings[0] = new_settings[0] & ~termios.ICRNL
    new_settings[0] = new_settings[0] & ~termios.IGNCR

通常の動作を得るには、これら3つを消去する行を省略するだけです。入力翻訳は「オリジナル」であっても変わりません。

new_settings[1] = new_settings[1] & ~termios.OPOSTこの行は、他の出力フラグに関係なく、すべての出力処理を無効にします。出力処理をそのまま維持するには、これを無視できます。これは生モードでも出力を「ノーマル」に保ちます。 (入力が自動的にエコーされるかどうかには影響しません。これはcflag ECHOin new_settings[3]。)

最後に、新しいプロパティを設定すると、次の条件が満たされた場合、呼び出しは成功します。どのの新しい設定が設定されました。設定が機密である場合(たとえば、コマンドラインからパスワードを要求する場合)、新しい設定をインポートして重要なフラグが正しく設定/設定解除されていることを確認する必要があります。

現在の端末設定を表示するには、次を実行します。

stty -a

入力フラグは通常4行目にあり、出力フラグは5行目にあります。-フラグが設定されていない場合、フラグ名がフラグ名の前に追加されます。たとえば、出力は次のようになります。

speed 38400 baud; rows 58; columns 205; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = M-^?; eol2 = M-^?; swtch = M-^?; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R; werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 hupcl -cstopb cread -clocal -crtscts
-ignbrk brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff -iuclc ixany imaxbel iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt echoctl echoke

擬似端末とUSB TTYデバイスでは、転送速度は重要ではありません。

パスワードなどを読みたい Bash スクリプトを作成する場合は、次の慣用語を検討してください。

#!/bin/bash
trap 'stty sane ; stty '"$(stty -g)" EXIT
stty -echo -echonl -imaxbel -isig -icanon min 1 time 0

EXITトラップはシェルが終了するたびに実行されます。stty -gスクリプトの起動時に端末の現在の設定を読み、スクリプトの終了時に現在の設定を自動的に復元します。Ctrl+interruptスクリプトを使用してC正しい操作を実行することもできます。 (信号がある特別な場合は、端末が元の/非正規の設定で停止することがありましたが(reset端末に+を盲目的に入力する必要があります)、実際の元の設定を復元する前に実行すると、毎回問題が解決しました。なぜ存在するのか。 )Enterstty sane

組み込みのbashを使用して(ターミナルにエコーせずに)入力行を読み取るか、次のようにread入力文字を文字ごとに読み取ることもできます。

IFS=$'\0'
input=""
while read -N 1 c ; do
    [[ "$c" == "" || "$c" == $'\n' || "$c" == $'\r' ]] && break
    input="$input$c"
done

IFSASCII NULに設定されていない場合、read組み込み機能は区切り文字を使用して空にcなります。若い選手に罠。

関連情報