Поки відповідь Томаса Дікі є цілком правильною, Стефан Шазелас правильно згадував у коментарі до відповіді Дікі, що перетворення не встановлено в камінь; це частина лінійної дисципліни.
Насправді переклад є повністю програмованим.
Сторінка man 3 terios містить в основному всю відповідну інформацію. (Посилання стосується проекту man-pages Linux , в якому зазначається, які функції є лише для Linux, а які є загальними для POSIX або інших систем; завжди перевірте розділ Conforming to Conforming на кожній сторінці.)
В iflag
атрибутах терміналу ( old_settings[0]
в коді , показаної на питання в Python ) мають три відповідні прапори на всі системи POSIXy:
INLCR
: Якщо встановлено, переведіть NL на CR на вхід
ICRNL
: Якщо встановлено (і IGNCR
не встановлено), переведіть CR на NL на вхід
IGNCR
: Ігноруйте CR на вході
Так само є і відповідні налаштування виводу ( old_settings[1]
), також:
OPOST
: Увімкнути обробку виводу.
OCRNL
: Позначте CR на NL на виході.
ONLCR
: Позначте NL на CR на виході. (XSI; недоступний у всіх системах POSIX або Single-Unix-специфікація.)
ONOCR
: Пропустити (не виводити) CR у першому стовпці.
ONLRET
: Пропустити (не виводити) CR.
Наприклад, ви можете уникнути покладання на tty
модуль. Операція "makeraw" просто очищає набір прапорів (і встановлює CS8
thelaglag):
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
хоча для сумісності, ви можете спочатку перевірити, чи всі ці константи існують в модулі терміни (якщо ви працюєте на системах, які не є POSIX). Ви також можете використовувати new_settings[6][termios.VMIN]
та new_settings[6][termios.VTIME]
встановити, чи буде блокування читання, якщо немає даних, що очікують, та як довго (у цілій кількості десятків секунд). (Зазвичай VMIN
встановлюється 0, і VTIME
0, якщо читання має повернутися негайно, або до позитивного числа (десятої секунди), скільки часу очікування має чекати не більше.)
Як бачимо, вищевказане (та "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
Щоб отримати нормальну поведінку, просто опустіть рядки, очищаючи ці три рядки, і вхідний переклад не зміниться навіть тоді, коли він "сирий".
new_settings[1] = new_settings[1] & ~termios.OPOST
Рядок відключає всі обробку виведення, незалежно від того, що говорять інші вихідні прапори. Ви можете просто опустити його, щоб зберегти обробку виводу недоторканою. Це підтримує вихід "нормальним" навіть у сирому режимі. (Це не впливає на те, чи введення автоматично лунає чи ні; це контролюється ECHO
cflag в new_settings[3]
.)
Нарешті, коли встановлені нові атрибути, виклик буде успішним, якщо було встановлено будь-яке з нових параметрів. Якщо налаштування є чутливими - наприклад, якщо ви запитуєте пароль у командному рядку -, ви повинні отримати нові налаштування та переконатися, що важливі прапори правильно встановлені / зняті, щоб бути впевненим.
Якщо ви хочете побачити свої поточні налаштування терміналу, запустіть
stty -a
Вхідні прапори зазвичай знаходяться на четвертому рядку, а вихідні прапори - на п’ятому рядку з -
попереднім іменем прапора, якщо прапор не встановлений. Наприклад, вихід може бути
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
він буде порожнім. Пастка для молодих гравців.