【问题标题】:Why does `^M` appear in terminal output when looking at some files?为什么在查看某些文件时,终端输出中会出现“^M”?
【发布时间】:2020-04-27 12:26:12
【问题描述】:

我正在尝试使用 curl 将文件发送到端点并将文件保存到机器。

从 Linux 发送 curl 并将其保存在机器上效果很好, 但在 Windows 中执行相同的 curl 操作是将 ^M 字符添加到行尾。

我在保存之前打印文件,但看不到^M。只有在保存后查看远程计算机上的文件才会显示^M

简单的字符串替换似乎不起作用。

为什么要添加^M?我怎样才能防止这种情况发生?

【问题讨论】:

    标签: linux terminal ascii control-characters


    【解决方案1】:

    快速回答:那是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 风格的行尾。

    【讨论】:

    • 非常感谢您的快速回答。说使用dos2unix,你的意思是this npm module
    • @Sariel 这是我所指的工具的 javascript 包装器 (this)。该工具预装在我的发行版 (/usr/bin/dos2unix) 上,但对于某些发行版,必须通过您的包管理器下载(例如 ubuntu 上的 sudo apt install dos2unix)。
    • @Sariel 但 NPM 模块的行为应该与实际工具相同,因此如果您愿意,可以使用它。
    • 谢谢,这是一个很好的解决方案。我发现了另一件事:在 windows 中的 notepad++ 中打开一个文件并将文件类型更改为 Unix 来解决这个问题(单击编辑 > EOL 对话 > Unix)。也许它会帮助某人:)
    • @Sariel 是的!大多数值得一提的跨平台文本编辑器都支持可配置的行尾。如果您使用 git,您可能还喜欢它在 windows 上的选项,可以自动将 windows 上的行尾转换为原生使用,同时保持远程存储库 unix 样式。
    猜你喜欢
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-26
    • 2010-12-21
    • 1970-01-01
    相关资源
    最近更新 更多