![Заставляет ли bash терминал преобразовывать символ новой строки (\n) в символ возврата каретки (\r)?](https://rvso.com/image/111971/%D0%97%D0%B0%D1%81%D1%82%D0%B0%D0%B2%D0%BB%D1%8F%D0%B5%D1%82%20%D0%BB%D0%B8%20bash%20%D1%82%D0%B5%D1%80%D0%BC%D0%B8%D0%BD%D0%B0%D0%BB%20%D0%BF%D1%80%D0%B5%D0%BE%D0%B1%D1%80%D0%B0%D0%B7%D0%BE%D0%B2%D1%8B%D0%B2%D0%B0%D1%82%D1%8C%20%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%20%D0%BD%D0%BE%D0%B2%D0%BE%D0%B9%20%D1%81%D1%82%D1%80%D0%BE%D0%BA%D0%B8%20(%5Cn)%20%D0%B2%20%D1%81%D0%B8%D0%BC%D0%B2%D0%BE%D0%BB%20%D0%B2%D0%BE%D0%B7%D0%B2%D1%80%D0%B0%D1%82%D0%B0%20%D0%BA%D0%B0%D1%80%D0%B5%D1%82%D0%BA%D0%B8%20(%5Cr)%3F.png)
Я открыл два терминала и из терминала ниже выполнил команду cat
чтения из терминала выше:
В терминале выше я набираю "Hello World<Enter>Bye"
, но, похоже, терминал выше отправил клавишу Enter
как возврат каретки ( \r
).
Так нужно ли bash
изменить настройки терминала, чтобы он переводил символ новой строки ( \n
) в символ возврата каретки ( \r
)?
решение1
Bash изменил терминал на "сырой" режим, что означает, что символы typer не обрабатываются никаким образом. Клавиша Enter создает символ возврата каретки (\r), а не перевода строки (\n), поэтому преобразование не происходит.
решение2
сыройиприготовленныйрежимы — описательные термины. stty raw
использует другие настройки, чем bash.
Bash выполняет инициализацию терминала вподготовить_настройки_терминала(внутренняя функция библиотеки readline), устанавливающая режим терминала, позволяющий считывать по одному символу за раз без вывода на экран:
tiop->c_lflag &= ~(ICANON | ECHO);
Однако перевод возврата каретки сбрасывается вдругая часть функции:
/* Make sure we differentiate between CR and NL on input. */
tiop->c_iflag &= ~(ICRNL | INLCR);
Если сравнить prepare_terminal_settings
сcoreutilsstty
, последний делает меньше (несколько пунктов, но bash INLCR
также сбрасывает):
иначе если (STREQ (информация->имя, "сырой") || STREQ (информация->имя, "приготовленный")) { если ((info->name[0] == 'r' && перевернуто) || (info->name[0] == 'c' && !перевернуто)) { /* Режим приготовления. */ режим->c_iflag |= BRKINT | ИГНПАР | ИСТРИП | МКРНП | ИКСОН; режим->c_oflag |= OPOST; режим->c_lflag |= ISIG | ИКАНОН; #если VMIN == VEOF режим->c_cc[VEOF] = CEOF; #endif #если VTIME == VEOL режим->c_cc[VEOL] = CEOL; #endif } еще { /* Необработанный режим. */ режим->c_iflag = 0; режим->c_oflag &= ~OPOST; режим->c_lflag &= ~(ISIG | ICANON #ifdef XCASE | X-КЕЙС #endif ); режим->c_cc[VMIN] = 1; режим->c_cc[VTIME] = 0; } }
POSIX говорит оstty raw
:
Включить (отключить) необработанный ввод и вывод. Необработанный режим должен быть эквивалентен настройке:
stty cs8 erase ^- kill ^- intr ^- \
quit ^- eof ^- eol ^- -post -inpck
что, что достаточно интересно (следуя описаниям -post
и -inpck
), не решает проблему перевода возврата каретки при вводе.
Так как условиясыройиприготовленный(либо POSIX, либо coreutils stty) не соответствуют тому, что делает bash, поэтому следует упомянуть функции POSIX termios, которые соответствуют тому, что он на самом деле делает:icrnl
(ввод перевода возврата каретки на новую строку).