Sementara jawaban Thomas Dickey cukup benar, Stéphane Chazelas dengan benar disebutkan dalam komentar atas jawaban Dickey bahwa pertobatannya tidak dilakukan dengan keras; itu adalah bagian dari garis disiplin.
Bahkan, terjemahannya sepenuhnya dapat diprogram.
Halaman manual man 3 termios pada dasarnya berisi semua informasi terkait. (Tautan ke proyek man-pages Linux , yang menyebutkan fitur mana yang hanya Linux, dan yang umum untuk POSIX atau sistem lain; selalu periksa bagian Menyesuaian untuk pada setiap halaman di sana.)
The iflagatribut terminal ( old_settings[0]dalam kode yang ditunjukkan di pertanyaan di Python ) memiliki tiga bendera yang relevan pada semua sistem POSIXy:
INLCR: Jika diatur, terjemahkan NL ke CR pada input
ICRNL: Jika diatur (dan IGNCRtidak diatur), terjemahkan CR ke NL pada input
IGNCR: Abaikan CR pada input
Demikian pula, ada pengaturan keluaran terkait ( old_settings[1]), juga:
OPOST: Aktifkan pemrosesan keluaran.
OCRNL: Peta CR ke NL pada output.
ONLCR: Peta NL ke CR pada output. (XSI; tidak tersedia di semua sistem POSIX atau Single-Unix-Specification.)
ONOCR: Lewati (jangan keluaran) CR di kolom pertama.
ONLRET: Lewati (jangan keluaran) CR.
Misalnya, Anda dapat menghindari mengandalkan ttymodul. Operasi "makeraw" hanya membersihkan satu set bendera (dan mengatur CS8oflag):
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
meskipun demi kompatibilitas, Anda mungkin ingin memeriksa apakah semua konstanta itu ada di modul termios terlebih dahulu (jika Anda menjalankan sistem non-POSIX). Anda juga dapat menggunakan new_settings[6][termios.VMIN]dan new_settings[6][termios.VTIME]untuk mengatur apakah pembacaan akan memblokir jika tidak ada data yang tertunda, dan berapa lama (dalam bilangan bulat deciseconds). (Biasanya VMINdiatur ke 0, dan VTIMEke 0 jika bacaan harus segera kembali, atau ke angka positif (sepersepuluh detik) berapa lama bacaan paling banyak menunggu.)
Seperti yang Anda lihat, di atas (dan "makeraw" secara umum) menonaktifkan semua terjemahan pada input, yang menjelaskan perilaku yang dilihat kucing:
new_settings[0] = new_settings[0] & ~termios.INLCR
new_settings[0] = new_settings[0] & ~termios.ICRNL
new_settings[0] = new_settings[0] & ~termios.IGNCR
Untuk mendapatkan perilaku normal, cukup hapus baris yang menghapus ketiga baris tersebut, dan terjemahan input tidak berubah bahkan ketika "mentah".
The new_settings[1] = new_settings[1] & ~termios.OPOSTgaris menonaktifkan semua proses output, terlepas apa bendera keluaran lain mengatakan. Anda bisa menghilangkannya agar proses pemrosesan output tetap utuh. Ini membuat output "normal" bahkan dalam mode mentah. (Itu tidak mempengaruhi apakah input secara otomatis digaungkan atau tidak; yang dikendalikan oleh ECHOcflag in new_settings[3].)
Akhirnya, ketika atribut baru diatur, panggilan akan berhasil jika ada pengaturan baru yang ditetapkan. Jika pengaturannya sensitif - misalnya, jika Anda meminta kata sandi pada baris perintah -, Anda harus mendapatkan pengaturan baru, dan memverifikasi bahwa tanda-tanda penting sudah diatur / tidak disetel dengan benar, untuk memastikan.
Jika Anda ingin melihat pengaturan terminal Anda saat ini, jalankan
stty -a
Bendera input biasanya di baris keempat, dan bendera output di baris kelima, dengan -mendahului nama bendera jika bendera tidak disetel. Misalnya, outputnya bisa
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
Pada pseudoterminals, dan perangkat USB TTY, baud rate tidak relevan.
Jika Anda menulis skrip Bash yang ingin dibaca misalnya kata sandi, pertimbangkan idiom berikut:
#!/bin/bash
trap 'stty sane ; stty '"$(stty -g)" EXIT
stty -echo -echonl -imaxbel -isig -icanon min 1 time 0
The EXITperangkap dijalankan setiap kali shell keluar. The stty -gmembaca pengaturan saat ini terminal pada awal script, sehingga pengaturan saat dikembalikan ketika keluar skrip, secara otomatis. Anda bahkan dapat mengganggu skrip dengan Ctrl+ C, dan itu akan melakukan hal yang benar. (Dalam beberapa kasus sudut dengan sinyal, saya telah menemukan bahwa terminal kadang-kadang macet dengan pengaturan mentah / noncanonical (memerlukan satu untuk mengetik reset+ Entersecara membabi buta di terminal), tetapi berjalan stty sanesebelum mengembalikan pengaturan asli yang sebenarnya telah sembuh bahwa setiap kali untuk saya. Jadi itu sebabnya ada di sana; semacam keamanan tambahan.)
Anda dapat membaca jalur input (tidak bertanda ke terminal) menggunakan readbash built-in, atau bahkan membaca input karakter demi karakter menggunakan
IFS=$'\0'
input=""
while read -N 1 c ; do
[[ "$c" == "" || "$c" == $'\n' || "$c" == $'\r' ]] && break
input="$input$c"
done
Jika Anda tidak disetel IFSke ASCII NUL, readbuilt-in akan mengkonsumsi separator, sehingga cakan kosong. Perangkap untuk pemain muda.