Während die Antwort von Thomas Dickey ganz richtig ist, hat Stéphane Chazelas in einem Kommentar zu Dickeys Antwort richtig erwähnt, dass die Bekehrung nicht in Stein gemeißelt ist; Es ist Teil der Liniendisziplin.
Tatsächlich ist die Übersetzung vollständig programmierbar.
Die man 3 termios- Manpage enthält grundsätzlich alle relevanten Informationen. (Der Link führt zu einem Linux-Handbuchprojekt , in dem angegeben ist, welche Funktionen nur für Linux gelten und welche für POSIX- oder andere Systeme gleich sind. Überprüfen Sie dort immer den Abschnitt Übereinstimmung mit auf jeder Seite.)
Die iflag
Terminalattribute ( old_settings[0]
in dem in der Frage in Python gezeigten Code ) weisen auf allen POSIXy-Systemen drei relevante Flags auf:
INLCR
: Falls gesetzt, NL bei der Eingabe in CR übersetzen
ICRNL
: Wenn gesetzt (und IGNCR
nicht gesetzt), wird CR bei der Eingabe in NL übersetzt
IGNCR
: CR bei der Eingabe ignorieren
Ebenso gibt es auch verwandte Ausgabeeinstellungen ( old_settings[1]
):
OPOST
: Aktiviert die Ausgabeverarbeitung.
OCRNL
: CR auf NL bei der Ausgabe abbilden.
ONLCR
: Bei der Ausgabe NL auf CR abbilden. (XSI; nicht in allen POSIX- oder Single-Unix-Spezifikationssystemen verfügbar.)
ONOCR
: CR in der ersten Spalte überspringen (nicht ausgeben).
ONLRET
: CR überspringen (nicht ausgeben).
Sie könnten beispielsweise vermeiden, sich auf das tty
Modul zu verlassen. Die "makeraw" -Operation löscht nur eine Reihe von Flags (und setzt die 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
Aus Kompatibilitätsgründen sollten Sie jedoch zunächst prüfen, ob alle diese Konstanten im Modul termios vorhanden sind (wenn Sie auf Nicht-POSIX-Systemen ausgeführt werden). Sie können auch mit new_settings[6][termios.VMIN]
und new_settings[6][termios.VTIME]
festlegen, ob und wie lange ein Lesevorgang blockiert werden soll, wenn keine Daten anstehen (in ganzzahligen Anzahl von Entscheidungssekunden). ( Wird normalerweise VMIN
auf 0 und VTIME
auf 0 gesetzt, wenn Lesevorgänge sofort zurückgegeben werden sollen, oder auf eine positive Zahl (Zehntelsekunden), wie lange der Lesevorgang höchstens warten soll.)
Wie Sie sehen können, deaktivieren die obigen (und "Makeraw" im Allgemeinen) alle Übersetzungen bei der Eingabe, was das Verhalten erklärt, das Katze sieht:
new_settings[0] = new_settings[0] & ~termios.INLCR
new_settings[0] = new_settings[0] & ~termios.ICRNL
new_settings[0] = new_settings[0] & ~termios.IGNCR
Um ein normales Verhalten zu erzielen, lassen Sie die Zeilen weg, die diese drei Zeilen löschen, und die Eingabeübersetzung bleibt auch bei "roh" unverändert.
Die new_settings[1] = new_settings[1] & ~termios.OPOST
Zeile deaktiviert die gesamte Ausgabeverarbeitung, unabhängig davon, was die anderen Ausgabe-Flags sagen. Sie können es einfach weglassen, um die Ausgabeverarbeitung intakt zu halten. Dadurch bleibt die Ausgabe auch im Raw-Modus "normal". (Es hat keinen Einfluss darauf, ob die Eingabe automatisch wiedergegeben wird oder nicht. ECHO
Dies wird durch das Flag in gesteuert new_settings[3]
.)
Wenn neue Attribute festgelegt werden, ist der Aufruf erfolgreich, wenn eine der neuen Einstellungen festgelegt wurde. Wenn die Einstellungen vertraulich sind - beispielsweise wenn Sie in der Befehlszeile nach einem Kennwort fragen -, sollten Sie die neuen Einstellungen abrufen und sicherstellen, dass die wichtigen Flags richtig gesetzt / nicht gesetzt sind.
Wenn Sie Ihre aktuellen Terminaleinstellungen anzeigen möchten, führen Sie aus
stty -a
Die Eingabe-Flags befinden sich normalerweise in der vierten Zeile und die Ausgabe-Flags in der fünften Zeile, wobei -
dem Flag-Namen ein vorangestellt wird, wenn das Flag nicht gesetzt ist. Beispielsweise könnte die Ausgabe sein
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
Bei Pseudoterminals und USB-TTY-Geräten spielt die Baudrate keine Rolle.
Wenn Sie Bash-Skripte schreiben, die z. B. Passwörter lesen möchten, berücksichtigen Sie die folgende Redewendung:
#!/bin/bash
trap 'stty sane ; stty '"$(stty -g)" EXIT
stty -echo -echonl -imaxbel -isig -icanon min 1 time 0
Die EXIT
Trap wird ausgeführt, wenn die Shell beendet wird. Der stty -g
liest die aktuellen Einstellungen des Terminals zu Beginn des Skripts, sodass die aktuellen Einstellungen beim Beenden des Skripts automatisch wiederhergestellt werden. Sie können das Skript sogar mit Ctrl+ unterbrechen C, und es wird das Richtige tun. (In einigen Eckfällen mit Signalen habe ich festgestellt, dass das Terminal manchmal mit den rohen / nicht-kanonischen Einstellungen feststeckt (es muss reset
+ Enterblind am Terminal eingegeben werden), aber stty sane
vor dem Wiederherstellen der tatsächlichen ursprünglichen Einstellungen wurde dies jedes Mal behoben Ich. Deshalb ist es da, eine Art zusätzliche Sicherheit.)
Sie können Eingabezeilen (die nicht an das Terminal gesendet wurden) mit der integrierten read
Bash-Funktion lesen oder die Eingabe sogar zeichenweise mit der Funktion lesen
IFS=$'\0'
input=""
while read -N 1 c ; do
[[ "$c" == "" || "$c" == $'\n' || "$c" == $'\r' ]] && break
input="$input$c"
done
Wenn Sie nicht IFS
auf ASCII NUL setzen, read
werden die Trennzeichen von der integrierten Funktion verbraucht, sodass c
sie leer sind. Falle für junge Spieler.