为什么 ^M 和 \r 表现不一致?

mga*_*ort 12 terminal-emulator terminal history ascii control-characters

也许已经有一些答案可以间接回答我的问题,但我已经阅读了很多,但尚未找到对这种差异的满意答案。

回车的本义来自老式电传打字机:它的意思是将打印头在当前行中向左移动。如果您继续在当前行写入,您将覆盖已经写入的内容。如今,我们可以使用文本符号来指定这种行为\r,它是在字符串中明确输入的。例如,在 Python 中您可以执行print('hello\rgoodbye'),而在终端中您可以执行echo $'hello\rgoodbye',并且在这两种情况下您都只会看到goodbye.

相比之下,伪回车也可以与 ASCII 控制字符^M(用Ctrl-M或键入Enter)交互插入。我称它为伪回车是因为尽管它被广泛称为回车\r,但令人惊讶的是它没有 insert ,而是 inserts \n,这是换行的符号。

因此,交互式键入hello, then Ctrl-M, thengoodbye出人意料地没有达到 的等价物hello\rgoodbye,而是相当于hello\ngoodbye.

这不是很矛盾吗?这背后的原理是什么?

Ste*_*itt 19

这是终端输入处理的结果:默认情况下,终端设备驱动程序(操作系统内核中用于处理终端输入的软件,而不是终端本身)转换CtrlMCtrlJ. 你可以通过运行看到这一点

od -t x1
Run Code Online (Sandbox Code Playgroud)

然后输入两个字符:

$ od -t x1
^M
^J
^D
0000000 0a 0a
0000002
Run Code Online (Sandbox Code Playgroud)

(你不会^M在屏幕上看到等。)

因此,当您键入 时CtrlM,无论程序正在处理您的输入,都不会看到回车,而是会看到换行符。

这可以用stty icrnl. 有关类似问题请参阅了解 Return、Enter 和 stty icrlf

  • 我不确定何时将 `icrnl` 添加到 termio 或 termios,但 Unix 总是在其内部期望和终端工作方式(从 Multics 继承)之间分离;我不确定事情是否会发生分歧,在创建 Unix 时终端已经发生了变化。[我在 Retro.SE 上写的这个相关答案](https://retrocomputing.stackexchange.com/a/6384/79) 进入了一些历史并提供了指向更详细解释的指针。 (3认同)