一方でトーマス・ディッキーの答えは非常に正確である、ステファンChazelasは正しく変換が石に設定されていないことディッキーの回答にコメントで述べました。それはライン規律の一部です。
実際、翻訳は完全にプログラム可能です。
男3つのtermiosの manページには、基本的にすべての関連情報が含まれています。(リンクはLinuxのman-pagesプロジェクトに移動します。このプロジェクトでは、Linux専用の機能と、POSIXまたは他のシステムに共通の機能が記載されています。常に各ページのConforming toセクションを確認してください。)
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またはSingle-Unix-Specificationシステムで使用できるわけではありません。)
ONOCR
:最初の列のCRをスキップします(出力しません)。
ONLRET
:スキップ(出力しない)CR。
たとえば、tty
モジュールに依存しないようにすることができます。「makeraw」操作は、フラグのセットをクリアするだけです(そしてCS8
oflag を設定します)。
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システムで実行する場合)。また、を使用new_settings[6][termios.VMIN]
しnew_settings[6][termios.VTIME]
て、保留中のデータがない場合に読み取りをブロックするかどうか、およびその長さ(整数デシ秒単位)を設定できます。(通常VMIN
は0に設定され、VTIME
読み取りがすぐに返される場合は0に、読み取りが最大で待機する時間(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
行は、他の出力フラグの内容に関係なく、すべての出力処理を無効にします。出力処理をそのまま維持するために、単に省略できます。これにより、rawモードでも出力が「通常」に維持されます。(入力が自動的にエコーされるかどうかには影響しません。それはのECHO
cflag によって制御され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+を使用してスクリプトを中断することもできCますが、それは正しいことをします。(信号があるいくつかのコーナーケースでは、端末が時々生/非標準設定で立ち往生することがわかりました(端末でタイプreset
+ Enter盲目的に入力する必要があります)がstty sane
、実際の元の設定を復元する前に実行すると、私です。だからそこにあるのです。一種の安全性です。)
read
bashビルトインを使用して(端末に選択されていない)入力行を読み取ることができます。
IFS=$'\0'
input=""
while read -N 1 c ; do
[[ "$c" == "" || "$c" == $'\n' || "$c" == $'\r' ]] && break
input="$input$c"
done
IFS
ASCII NULに設定しない場合、read
ビルトインは区切り文字を消費するため、区切り文字はc
空になります。若い選手のためのrap。