Unix / Linux EOL - LF, перевод строки, ASCII 10, escape-последовательность \n
.
Вот фрагмент кода 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; почему Enterдают 13, а не 10?
Ответы:
В то время как ответ Томаса Дики является вполне правильным, Стефан Шазелас правильно упомянул в комментарии к ответу Дики, что преобразование не является каменным; это часть дисциплины линии.
На самом деле перевод полностью программируемый.
Страница man man 3 termios содержит в основном всю необходимую информацию. (Ссылка относится к проекту man-страниц Linux , в котором упоминаются, какие функции доступны только для Linux, а какие являются общими для POSIX или других систем; всегда проверяйте раздел Соответствие на каждой странице.)
У
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-Specification.)ONOCR
: Пропустить (не выводить) CR в первом столбце.ONLRET
: Пропустить (не выводить) CR.Например, вы можете не полагаться на
tty
модуль. Операция "makeraw" просто очищает набор флагов (и устанавливаетCS8
флаг):хотя для совместимости вы можете сначала проверить, существуют ли все эти константы в модуле termios (если вы работаете в системах, отличных от POSIX). Вы также можете использовать
new_settings[6][termios.VMIN]
и,new_settings[6][termios.VTIME]
чтобы указать, будет ли чтение блокироваться, если нет ожидающих данных, и как долго (в целых числах в децисекундах). (ОбычноVMIN
устанавливается в 0 иVTIME
в 0, если чтения должны немедленно вернуться, или к положительному числу (десятые секунды), как долго чтение должно ждать максимально.)Как вы можете видеть, вышеприведенное (и вообще «makeraw») отключает все переводы при вводе, что объясняет поведение, которое видит cat:
Чтобы получить нормальное поведение, просто опустите строки, очищающие эти три строки, и входной перевод останется неизменным, даже если он «сырой».
new_settings[1] = new_settings[1] & ~termios.OPOST
Строка отключает все обработку вывода, независимо от того, что говорят другие выходные флаги. Вы можете просто опустить его, чтобы сохранить обработку вывода без изменений. Это сохраняет вывод "нормальным" даже в необработанном режиме. (Это не влияет на то, будет ли ввод автоматически отражаться или нет; это контролируетсяECHO
cflag innew_settings[3]
.)Наконец, когда заданы новые атрибуты, вызов будет успешным, если были установлены какие-либо новые настройки. Если настройки чувствительны - например, если вы запрашиваете пароль в командной строке - вы должны получить новые настройки и убедиться, что важные флаги правильно установлены / не установлены, чтобы быть уверенными.
Если вы хотите увидеть текущие настройки терминала, запустите
Флаги ввода обычно находятся в четвертой строке, а флаги вывода - в пятой строке, с
-
предшествующим именем флага, если флаг не установлен. Например, вывод может бытьНа псевдотерминалах и устройствах USB TTY скорость передачи данных не имеет значения.
Если вы пишете скрипты Bash, которые хотят читать, например, пароли, рассмотрите следующую идиому:
EXIT
Ловушка выполняется всякий раз , когда оболочка завершает свою работу.stty -g
Считывает текущие параметры терминала в начале сценария, так что текущие настройки будут восстановлены при выходе из сценария, автоматически. Вы можете даже прервать сценарий с помощью Ctrl+ C, и он будет делать правильные вещи. (В некоторых угловых случаях с сигналами я обнаружил, что терминал иногда застревает с необработанными / неканоническими настройками (требуется один для слепого набораreset
+ Enterв терминале), но работаstty sane
перед восстановлением фактических исходных настроек вылечивает, что каждый раз для я. Так вот почему это там, своего рода дополнительная безопасность.)Вы можете читать входные строки (не подключенные к терминалу), используя
read
встроенный bash, или даже читать ввод за символом, используяЕсли вы не установите
IFS
ASCII NUL,read
встроенный будет использовать разделители, так чтоc
он будет пустым. Ловушка для молодых игроков.источник
По сути, «потому что это было сделано так с ручных пишущих машинок». В самом деле.
Ручная пишущая машинка имела каретку, на которую подавалась бумага, и она двигалась вперед по мере того, как вы печатали (загружая пружину), и имела рычаг или ключ, который отпускал каретку, позволяя пружине возвращать каретку на левое поле.
Когда был введен электронный ввод данных (телетайп и т. Д.), Они продвинулись вперед. Таким образом, Enterключ на многих терминалах будет помечен Return.
Перевод строки произошел (в ручном режиме) после возврата каретки на левое поле. Опять же, электронные устройства имитировали ручные устройства, делая отдельную line-feedоперацию.
Обе операции закодированы (чтобы телетайп мог быть больше, чем автономное устройство, создающее тип бумаги), поэтому мы имеем
CR
(возврат каретки) иLF
(перевод строки). Это изображение из ASR 33 Teletype Information показывает клавиатуру,Return
справа иLine-Feed
слева. Находясь справа , это был главный ключ:Unix появился позже. Его разработчики любили сокращать вещи (посмотрите на все сокращения, даже
creat
для «создания»). Столкнувшись, возможно, с двумя частями процесса, они решили, что переводы строки имеют смысл только в том случае, если им предшествует возврат каретки. Поэтому они отбросили явные возвраты каретки из файлов и перевели Returnключ терминала для отправки соответствующего перевода строки. Просто, чтобы избежать путаницы, они называли перевод строки «новой строкой».При написании текста на терминале Unix переводит в другом направлении: перевод строки становится переводом каретки / переводом строки.
(То есть «обычно»: так называемый «режим приготовления», в отличие от «необработанного» режима, когда перевод не выполняется).
Резюме:
источник
LF
переводится вCR LF
. Когда вы набираетеfoo<Return>
в готовом режиме, приложение читаетfoo\n
иfoo\r\n
отсылается по дисциплине линии для эха на терминал.