回车,换行的区别

518 阅读6分钟

回车,换行的区别

符号ASCII码意义
\n10换行
\r13回车

为什么会有回车与换行?

在计算机还没有出现之前,有一种叫做电传打字机(Teletype Model 33,Linux/Unix下的tty概念也来自于此)的玩意,每秒钟可以打10个字符。但是它有一个问题,就是打完一行换行的时候,要用去0.2秒,正好可以打两个字符。要是在这0.2秒里面,又有新的字符传过来,那么这个字符将丢失。

于是,研制人员想了个办法解决这个问题,就是在每行后面加两个表示结束的字符。一个叫做“回车”,告诉打字机把打印头定位在左边界;另一个叫做“换行”,告诉打字机把纸向下移一行。这就是“换行”和“回车”的来历,从它们的英语名字上也可以看出一二。

后来,计算机发明了,这两个概念也就被般到了计算机上。那时,存储器很贵,一些科学家认为在每行结尾加两个字符太浪费了,加一个就可以。于是,就出现了分歧。

在 Windows 和 UNIX 系统中,换行符是不同的,这导致在处理文本文件时可能会遇到一些兼容性问题。下面是 Windows 和 UNIX 中换行符的区别:

  • Windows:在 Windows 系统中,换行符是由两个字符组成的:回车 (Carriage Return, CR) 和换行 (Line Feed, LF)。它们的 ASCII 编码分别是 13 和 10,通常一起使用,表示为 "\r\n"(在编程语言中通常这样表示)。
  • Unix/Linux:在 UNIX 和 Linux 系统中,换行符只是一个字符:换行 (Line Feed, LF)。它的 ASCII 编码是 10,表示为 "\n"
  • Mac OS(老版本,如 Mac OS 9 以前的版本):早期的 Mac OS 系统使用一个字符来表示换行:回车 (Carriage Return, CR),ASCII 编码为 13,表示为 "\r"。但是,从 Mac OS X 开始,Apple 转而使用 UNIX 标准的换行符,即 "\n"

在现代编辑器和开发环境中,往往能够智能地识别和处理不同系统的换行符,使得跨平台的文本处理变得更加容易。但如果你在用一些较为简单或古老的工具处理文本文件,这个问题就可能变得比较麻烦。在编程时,了解这个区别可以帮助你避免一些常见的问题和错误。

为了更好地理解 Windows 和 Unix 系统中的换行符差异,你可以创建一个小程序来生成包含特定换行符的文件,然后尝试在不同系统中打开它们来观察效果。下面是一个简单的 Java 程序,它创建三个文件:一个使用 \r\n 作为换行符,一个使用 \n,另一个使用 \r

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class NewlineExample {

    public static void main(String[] args) {
        String text = "Line 1%sLine 2%sLine 3%sLine 4";

        try {
            Files.write(Paths.get("windows_newline.txt"), String.format(text, "\r\n", "\r\n", "\r\n").getBytes());
            Files.write(Paths.get("unix_newline.txt"), String.format(text, "\n", "\n", "\n").getBytes());
            Files.write(Paths.get("old_mac_newline.txt"), String.format(text, "\r", "\r", "\r").getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个程序中:

  1. 我们首先定义了一个包含三个占位符(%s)的字符串模板。
  2. 然后我们使用 String.format 方法来创建三个不同版本的字符串,每个版本使用不同的换行符。
  3. 使用 Files.write 方法将这些字符串写入到不同的文件中。
  4. 这将创建三个文件,每个文件使用不同的换行符。

一旦你运行了这个程序并创建了这些文件,你可以尝试在不同的文本编辑器或系统中打开它们来查看效果。你会注意到不同的换行符会如何影响文本的显示。

Windows 自带的记事本在近年来已经得到了更新,以便能够正确处理 Unix 风格 (\n) 的换行符。早期版本的记事本无法正确处理只使用 \n 的文件,它们会将整个文档显示在一行中。

在 Windows 系统中,当你在记事本或其他文本编辑器中输入文本并按下 "Enter" 键来创建新的一行时,实际上是插入了一个 \r\n (回车符跟着换行符) 序列来表示新行。

如果你想验证这一点,你可以用一个能够显示非打印字符的文本编辑器(如 Notepad++ 或 Visual Studio Code)来打开文件,或者你可以写一个小程序来读取文件的原始字节来检查它。这里是一个简单的 Java 程序,它将读取一个文件的所有字节并打印它们:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

public class ReadFileExample {

    public static void main(String[] args) {
        try {
            byte[] bytes = Files.readAllBytes(Paths.get("path_to_your_file.txt"));
            for (byte b : bytes) {
                System.out.print(b);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在这个程序中,你将看到文件中的每个字符的ASCII码都被打印出来,包括换行符。你可以留意\r\n 的 ASCII 值(分别是 13 和 10)来确认文件中实际使用的换行符。

不同系统使用的换行符不同,这必然会引发兼容性问题

在 Windows 系统中编辑一个 Bash 脚本并将其发送给 Linux 系统来运行,是可能会遇到一些问题的,主要是因为 Windows 默认使用 \r\n 作为换行符,而 Linux 使用 \n。这种差异可能会导致脚本在 Linux 系统上出现问题。

幸运的是,大多数现代的文本编辑器和 IDE 可以让你选择要使用的换行符类型。在你保存脚本之前,你应该确保将换行符设置为 Unix/Linux 格式(即 \n)。这样可以确保你的脚本将在 Linux 系统上正常工作。

如果你已经有一个使用 Windows 换行符的脚本,你可以使用 dos2unix 工具来转换它。这个工具可以将 Windows 换行符转换为 Unix 换行符,使脚本可以在 Linux 系统上运行。你可以像这样使用它:

dos2unix yourscript.sh

如果你不有 dos2unix 工具,可以通过以下命令来安装:

  • 在 Debian/Ubuntu 上:

    sudo apt update
    sudo apt install dos2unix
    
  • 在 Red Hat/CentOS/Fedora 上:

    sudo yum install dos2unix
    
  • 在 Arch Linux 上:

    sudo pacman -S dos2unix
    

一旦你有了这个工具,就可以很容易地转换脚本并在 Linux 系统上运行它。

相反的,在unix系统编辑的bat脚本无法在Windows系统上运行

你可以使用 unix2dos 命令来转换文件。这样它就可以在 Windows 上正确运行了。这是一个使用该工具的示例:

unix2dos yourscript.bat

注意,dos2unix 包同时提供了 dos2unixunix2dos 两个工具。