快速回答:那是carriage return。它们是 Windows 如何编码文本文件的无害但轻微刺激的工件。您可以使用dos2unix 将它们从文件中删除。您可以将大多数文本编辑器配置为使用“Unix 行尾”或“LF 行尾”,以防止它们出现在您将来从 Windows PC 创建的新文件中。
长答案(带有一些历史琐事):
在纯文本文件中,当您创建新行时(通过按 enter/return),文件中会嵌入“换行符”。在 Unix/Linux 上,这是一个单一的字符,'\n',即“换行符”。在 Windows 上,这是两个连续的字符,'\r\n',即“回车”,后跟“换行”。
当物理teletype terminals(其行为很像打字机)仍在使用时,“换行”字符表示“将纸张向上移动到下一行”,而“回车”字符表示“全部滑动回车”路过所以打字头在最左边”。从一开始,几乎所有的电传终端都支持隐式回车;即,触发换行将自动触发回车。致力于后来演变成 Windows 的开发人员决定最好包含显式回车,以防万一(出于某种原因)电传打字机不隐式执行回车。另一方面,Unix 开发人员选择使用隐式回车的假设。
回车和换行是ASCII Control Characters,这意味着它们没有作为独立可打印字符的可见表示,而是影响输出光标本身(在这种情况下,输出光标的位置)。
您看到的“^M”是回车符的替代表示,由不完全“烹饪”其输出的程序使用(即,不应用某些 ASCII 控制字符的效果) . (其他控制字符还有其他以“^”开头的表示,而“^”字符在nano等一些Unix程序中也用于表示“ctrl”键盘键。)
您可以使用dos2unix 将行尾从 Windows 样式转换为 Unix 样式。
$ curl https://example.com/file_with_crlf.txt | dos2unix > file.txt
在某些发行版中,此工具默认包含在内,在其他发行版中,它可以通过包管理器安装(例如,在 Ubuntu 上,sudo apt install dos2unix)。还有一个包,unix2dos,用于逆向。
大多数用于编码的“智能”文本编辑器(Sublime、Atom、VS Code、Notepad++ 等)都可以愉快地使用 Windows 风格或 Unix 风格的行尾进行读写(这可能需要更改一些配置选项)。通常,通过扫描文件的内容来自动检测行尾,并且通常使用操作系统的本机行尾创建新文件(默认情况下)。甚至新版本的Notepad 也支持Unix 风格的行尾。另一方面,一些 Unix 工具在出现 Windows 风格的换行符时会产生奇怪的结果。如果您的代码库将被 Unix 和 Windows 操作系统上的人们使用,那么最好的做法是在任何地方使用 Unix 风格的行尾。
Windows 上的 Git 也有一个可选模式,它用 Windows 样式的换行符签出所有文件,但用 Unix 样式的换行符将它们重新签入。
旁注(有趣,但与您的问题没有直接关系):
回车的实际作用(在现代虚拟终端上,无论是 Windows 还是 Unix)是将输出光标移动到行首。如果使用不带换行符的回车,则可以“覆盖”已打印的部分字符串。
$ printf "dogdog" ; printf "\rcat\n"
catdog
一些 Unix 程序使用它来异步更新最后一行输出的一部分,以实现诸如实时更新进度指示器之类的功能。例如,curl,如果文件内容通过管道传输到其他地方,则会在标准输出上显示下载进度。
另外:如果你有一个工具可以尽可能地解释 Windows 风格的行尾,并且你给它一个带有 Unix 风格的行尾的字符串,例如“hello\nworld”,你会得到这样的输出:
hello
world
幸运的是,这样的实现非常少见,而且一般来说,绝大多数 Windows 工具都可以毫无问题地渲染 Unix 风格的行尾与 Windows 风格的行尾。