为什么会出现“非法字符:^M”错误?
我遇到了某种我无法理解的格式问题,下面是使用 Zsh 的简短示例。为什么?
$ values=( 300 400 )
$ echo "scale=20; $values[1]-$values[2]" | bc
(standard_in) 1: illegal character: ^M // Why does it not print -100?
$ echo $values // no ^M sign found!
300 400
帮助问题
- 为什么 ASCII 中的第 13 个字符是
5E 4d 0a
,即^M
?- 为什么结尾符号“0a”显示为点“.”?这 ”。”十六进制的“2E”。
I got some sort of formatting -problem that I cannot understand, a short example below using Zsh. Why?
$ values=( 300 400 )
$ echo "scale=20; $values[1]-$values[2]" | bc
(standard_in) 1: illegal character: ^M // Why does it not print -100?
$ echo $values // no ^M sign found!
300 400
Helper questions
- Why is
5E 4d 0a
, ie^M
, 13th char in ASCII?- Why is the ending sign "0a" shown as a dot "."? The "." is "2E" in Hex.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Unix 和 Windows 有不同的行结束格式。在 Unix 世界中,行以换行符(LF,ascii char 10)结束。 Windows 以回车符(CR,ascii char 13)和换行符结束行。
具有 Windows 行结尾的文件必须先转换为 Unix 格式,然后才能使用 Unix 工具。否则像
bc
这样的程序会将 CR 字符视为垃圾并抱怨,就像您的情况一样。要将文件转换为 Unix 格式,您可以使用
dos2unix(1)
(如果已安装),或者通过sed 's/^M//g'
传递它(但不要输入文字 ^M - 按 Ctrl+V,然后按 Ctrl+M)。那么为什么是
^M
呢?好吧,回车符是一个不可打印的字符。它没有可打印的表示。为了方便起见,您的终端会将其显示为^M
*。那么为什么当您执行echo $values
时它没有出现呢?不幸的是,命令行参数处理将其删除,因此您看不到它。另外,为了方便起见,您的终端允许您通过 Ctrl+V 和 Ctrl + 某个字母键入不可打印的字符。 Ctrl+V 和 Ctrl+M 将产生一个
^M
字符,但左右移动光标,您会看到它作为单个字符跳过整个内容 - 不是 与输入^
后跟M
相同。虽然您看到^M
,但命令行程序只能看到原始数据,并且会看到实际的回车符。您在
echo "^M"
的输出上运行了hexdump
,它生成三个字符:^
、M
> 和换行符 (LF)。请看上面,这与回车符不同!Hexdump 将所有不可打印字符显示为
.
字符,包括回车符和换行符。*为什么特别是M?约定是在 ASCII 码上加 64。回车符是 ASCII 代码 13 (0x0D)。添加 64,得到 77 (0x4D),这是一个大写的 M。请参阅此页了解完整列表。
Unix and Windows have different line ending formats. In the Unix world, lines end with the linefeed character (LF, ascii char 10). Windows ends lines with a carriage return (CR, ascii char 13) followed by a linefeed.
Files with Windows line endings must be converted to Unix format before they can work with Unix tools. Otherwise programs like
bc
see the CR characters as junk and complain, as in your case.To convert files to Unix format, you can use
dos2unix(1)
if you have it installed, or alternately pass it throughsed 's/^M//g'
(but don't type a literal ^M - press Ctrl+V, followed by Ctrl+M).So why
^M
? Well, the carriage return is a nonprintable character. It has no printable representation. For convenience, your terminal will display it as^M
*. So why didn't it appear when you didecho $values
? Unfortunately, the command line argument processing strips it out, so you don't see it.Also for your convenience, your terminal allows you to type nonprintable characters via Ctrl+V and Ctrl + some letter. Ctrl+V and Ctrl+M will produce a
^M
character, but move your cursor left and right and you'll see it skips over the whole thing as a single character - not the same as typing^
followed byM
. While you see^M
, command line programs see only the raw data, and will see an actual carriage return character.You ran
hexdump
on the output ofecho "^M"
, which produces three characters: a^
, aM
, and a linefeed character (LF). See above, that's not the same as a carriage return!Hexdump displays all non-printable characters as
.
characters, including carriage return and line feed characters.*Why M in particular? The convention is to add 64 to the ASCII code. A carriage return is ASCII code 13 (0x0D). Add 64 and you get 77 (0x4D) which is an uppercase M. See this page for a full listing.
^M 是一个字符 - 回车符是 dos/windows 或 ASCII 13 字符。看来你不知何故损害了你的输入,也许是通过粘贴 Windows 文件中的某些内容或类似的内容......
^M in one character - the Carriage Return is dos/windows, or ASCII 13 character. It seems that somehow you compromised your input, maybe by pasting something from a windows file or something like that...
如果您通过
dos2unix
运行您的文件(如果您的系统上有该程序),那么您的运气可能会更好。除此之外,
dos2unix
会将 Windows \r\n 行结尾转换为 Unix 风格的 \n 行结尾。You might have better luck if you run your file through
dos2unix
, if that program is available on your system.Among other things,
dos2unix
will convert the Windows \r\n line endings to Unix-style \n line endings.帮助者问题的答案
帮助示例的信息
Answers to Helper Questions
Information to help with the examples
我通过从
~/.gitconfig
中删除它来解决这个问题,由于某种原因,它会自动将
^M
附加到我的 vim-plug 插件并破坏 neovim。I fixed this by removing this from
~/.gitconfig
Which was appending
^M
to my vim-plug plugins automatically for some reason and breaking neovim.