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が表示されます。
存在するWindows、Enter送信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 ECHO
in 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
IFS
ASCII NULに設定されていない場合、read
組み込み機能は区切り文字を使用して空にc
なります。若い選手に罠。