\n
(换行符)和 \r
(回车符)有什么区别?
特别是,\n
和 \r
之间是否存在任何实际差异?有没有应该使用一个代替另一个的地方?
就 ascii 代码而言,它是 3——因为它们分别是 10 和 13;-)。
但说真的,有很多:
在 Unix 和所有类 Unix 系统中,\n 是行尾代码,\r 表示没什么特别的
因此,在 C 和大多数以某种方式复制它(甚至是远程)的语言中,\n 是行尾的标准转义序列(根据需要转换为/从操作系统特定的序列转换)
在旧的 Mac 系统(OS X 之前)中,\r 是行尾代码
在 Windows(和许多旧操作系统)中,行尾代码是 2 个字符,\r\n,按此顺序
作为(令人惊讶的;-)结果(回溯到比 Windows 更早的操作系统),\r\n 是 Internet 上文本格式的标准行终止符
对于类似机电电传打字机的“终端”,\r 命令托架向左返回,直到它碰到最左边的停止(慢速操作),\n 命令滚轮卷起一条线(快得多的操作)——这就是原因你总是在 \n 之前有 \r,这样滚轮可以在马车仍然向左移动时移动!-) 维基百科有更详细的解释。
对于字符模式终端(通常模拟上述更旧的打印终端),在原始模式下,\r 和 \n 的行为类似(除了光标方面,因为没有托架或滚轮;-)
在实践中,在写入文本文件的现代上下文中,您应该始终使用 \n
(如果您使用的是奇怪的操作系统,例如 Windows,则底层运行时将转换它;-)。使用 \r
的唯一原因是,如果您正在写入字符终端(或者更可能是模拟它的“控制台窗口”)并且希望您写入的下一行覆盖您刚刚编写的最后一行(有时用于愚蠢例如进度条的“ascii 动画”效果)——不过,这在 GUI 的世界中已经过时了;-)。
过去,\n
用于将托架向下移动,而 \r
用于将托架移回页面左侧。
printf("abcdefghijlm\rNOP\n");
在 OpenSuSe 上使用 gcc-8 编译并在终端上运行会产生此输出 NOPdefghijlm
。字符串中的 \r(回车)导致光标移动到行首(回车)并且 \r 后面的字符(即“NOP”)会覆盖之前的内容(即“abc”)!您可以使用退格 (\b) 实现类似的“马车移动”,就像在 printf("abcdefghijlm\b\bNOP\n");
中产生 abcdefghijNOP
两个不同的角色。
\n
在 Unix 文本文件中用作行尾终止符
\r
历史上(OS X 之前)在 Mac 文本文件中用作行尾终止符
\r\n
(即两者一起)用于终止 Windows 和 DOS 文本文件中的行。
\r
很长一段时间都不是 Mac 上的换行符。随着 2001 年 Mac OS X(基于 Unix)的发布,现在使用 \n
。
\r
- 例如 MS Office 2011 Excel:保存 CSV(使用所有默认设置) - 将保存以 \r
行结尾的 ISO-8859-1 编码文件。
由于没有其他人特别提到它(他们太年轻以至于不知道/记得吗?) - 我怀疑 \r\n
的使用起源于打字机和类似设备。
当您在使用具有多行功能的打字机时想要换行时,它必须执行两个物理操作:将托架滑回页面的开头(左侧,在美国),然后将纸张向上送入一个档位.
例如,在行式打印机时代,打印粗体文本的唯一方法是在没有换行的情况下执行回车并在旧字符上打印相同的字符,从而添加更多墨水,从而使其看起来更暗(粗体) .当打字机的机械“换行”功能失败时,这是令人讨厌的结果:如果你不注意的话,你可以在前一行文本上打字。
不同操作系统的两个不同字符。 这在通过 TCP/IP
传输的数据中也起作用,需要使用 \r\n
。
\n
Unix
\r
Mac
\r\n
Windows 和 DOS。
去完成,
在 shell (bash) 脚本中,您可以使用 \r
将光标放在前面,当然还有 \n
将光标放在新行上。
例如,尝试:
echo -en "AA--AA" ; echo -en "BB" ; echo -en "\rBB"
第一个“回声”显示AA--AA
第二个:AA--AABB
上一个:BB--AABB
但不要忘记使用 -en
作为参数。
在 Windows 中,\n
移动到下一行的开头。 \r
移动到当前行的开头,而不移动到下一行。我在自己的控制台应用程序中使用了 \r
,我在其中测试了一些代码并且我不想看到文本在我的屏幕上滚动,所以在打印出一些文本后使用 \n
,例如一个框架速率 (FPS),我将 printf("%-10d\r", fps);
这会将光标返回到行首而不向下移动到下一行,并允许我在屏幕上显示在帧速率不断更新时不会滚动的其他信息在同一行(%-10
确保输出至少为 10 个字符,左对齐,因此它最终被空格填充,覆盖该行的任何旧值)。对于这样的东西非常方便,通常当我将调试内容输出到我的控制台屏幕时。
一点历史
/r
代表 return 或 carriage return,它的历史归功于打字机。回车将您的马车一直向右移动,因此您在行首输入。
/n
代表 new line,同样,从打字机时代开始,您就下移到了新行。但这并不是一开始的,这就是为什么一些操作系统需要同时返回 /r
和 /n
换行符,因为这是打字机的顺序。它还解释了旧的 8 位计算机过去有 Return 而不是 Enter,来自熟悉的 回车。
\n (换行符)和 \r (回车符)有什么区别?特别是,\n 和 \r 之间有什么实际区别吗?有没有应该使用一个代替另一个的地方?
我想对换行符的 \n
和回车符的 \r
各自的转义序列做一个简短的实验,以说明它们之间的明显区别在哪里。
我知道,这个问题被问到与语言无关。尽管如此,我们至少需要一种语言来完成实验。在我的例子中,我选择了 C++,但该实验通常适用于任何编程语言。
该程序只是简单地迭代以将一个句子打印到控制台中,这是通过 for 循环迭代完成的。
换行程序:
#include <iostream>
int main(void)
{
for(int i = 0; i < 7; i++)
{
std::cout << i + 1 <<".Walkthrough of the for-loop \n"; // Notice `\n` at the end.
}
return 0;
}
输出:
1.Walkthrough of the for-loop
2.Walkthrough of the for-loop
3.Walkthrough of the for-loop
4.Walkthrough of the for-loop
5.Walkthrough of the for-loop
6.Walkthrough of the for-loop
7.Walkthrough of the for-loop
请注意,此结果不会在任何系统上提供,您正在执行此 C++ 代码。但它适用于最现代的系统。阅读下文了解更多详情。
现在,同样的程序,但不同的是,在打印序列结束时,\n
被替换为 \r
。
回车方案:
#include <iostream>
int main(void)
{
for(int i = 0; i < 7; i++)
{
std::cout << i + 1 <<".Walkthrough of the for-loop \r"; // Notice `\r` at the end.
}
return 0;
}
输出:
7.Walkthrough of the for-loop
注意到区别在哪里了吗?区别很简单,当您在每个打印序列的末尾使用回车转义序列 \r
时,该序列的下一次迭代不会进入以下文本行 - 在每个打印序列的末尾,光标没有跳到下一行的*开头。
相反,在使用 \r
字符之前,光标跳回到了他所在的行的开头。 - 结果是打印序列的每个后续迭代都替换了前一个迭代。
*注意:\n
不一定跳到以下文本行的开头。在某些更老的操作系统上,\n
换行符的结果可能是,它跳转到下一行的任何地方,而不仅仅是开头。这就是为什么他们需要使用 \r \n
来获取下一个文本行的开头。
该实验向我们展示了在打印序列迭代输出的上下文中换行符和回车符之间的区别。
在讨论程序中的输入时,一些终端/控制台可能会将回车隐式转换为换行符,以获得更好的可移植性、兼容性和完整性。
但是,如果您可以选择为另一个选择一个,或者想要或需要明确地只使用一个特定的,您应该始终使用符合其目的并严格区分的那个进行操作。
只是为了增加混乱,我一直在开发一个简单的文本编辑器,在浏览器的 HTML 页面中使用 TextArea 元素。考虑到 CR/LF 的兼容性问题,我编写了代码来检查平台,并使用适用于平台的任何换行约定。
然而,在检查 TextArea 中包含的实际字符时,我发现了一些有趣的事情,通过一个小的 JavaScript 函数生成与字符对应的十六进制数据。
对于测试,我输入了以下文本:
你好,世界[进入]
再见,残酷的世界[进入]
当我检查文本数据时,我得到的字节序列是这样的:
48 65 6c 6c 6f 2c 20 57 6f 72 6c 64 0a 47 6f 6f 64 62 79 65 2c 20 43 72 75 65 6c 20 57 6f 72 6c 64 0a
现在,大多数人看到这个,看到 0a 但没有 0d 字节,会认为这个输出是在 Unix/Linux 平台上获得的。但是,问题来了:我在 Windows 7 64 位的 Google Chrome 中获得的这个序列。
因此,如果您使用 TextArea 元素并检查文本,请像我在上面所做的那样检查输出,以确保从 TextArea 返回了哪些实际字符字节。我还没有看到这在其他平台或其他浏览器上是否有所不同,但如果您通过 JavaScript 执行文本处理,并且您需要使该文本处理平台独立,则值得牢记。
上述文章中涵盖的约定适用于控制台输出,但 HTML 元素似乎遵循 UNIX/Linux 约定。除非有人在不同的平台/浏览器上发现其他情况。
回车:将回车返回到行首
换行:将纸向上送一行
在屏幕输出的上下文中:
CR:将光标返回到当前行的开头
LF:光标下移一行
例如:
你好,\n世界\r!
应该在您的终端上呈现为:
Hello,
! world
某些操作系统可能会破坏与预期行为的兼容性,但这不会改变对“\n 和 \r 之间的区别?”问题的答案。
#include <stdio.h>
void main()
{
int countch=0;
int countwd=1;
printf("Enter your sentence in lowercase: ");
char ch='a';
while(ch!='\r')
{
ch=getche();
if(ch==' ')
countwd++;
else
countch++;
}
printf("\n Words = ",countwd);
printf("Characters = ",countch-1);
getch();
}
让我们以这个例子为例,尝试将 \n 代替 \r 它不起作用并尝试猜测为什么?
Return
和 Enter
的美好时光。甚至我的现代无线键盘仍然在旧的 Return
键上显示向下和返回箭头(现在标题为“Enter”以与数字键盘的 Enter
键一致,它不显示箭头)
\r\n
而不是 \r?\n
上拆分行时,此类错误/有问题的代码仍然很明显......这可以在不提供虚拟换行符的语言运行时的 Windows 代码库中找到。
不定期副业成功案例分享
\r
(我使用的是 Linux),我对此有过一些非常糟糕的经历。一旦我开始解析看似有效的文件,我的解析器就会失败,因为我正在解析的文件是在 Windows 中创建的。 :D 所有这一切的主要问题是\n
或\r
都不可见,例如a
、.
、(
等字符。