为什么会出现“非法字符:^M”错误?

发布于 2024-08-29 22:56:09 字数 486 浏览 8 评论 0原文

我遇到了某种我无法理解的格式问题,下面是使用 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

帮助问题

  1. 为什么 ASCII 中的第 13 个字符是 5E 4d 0a,即 ^M
  2. 为什么结尾符号“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

  1. Why is 5E 4d 0a, ie ^M, 13th char in ASCII?
  2. Why is the ending sign "0a" shown as a dot "."? The "." is "2E" in Hex.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

油焖大侠 2024-09-05 22:56:10

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,但命令行程序只能看到原始数据,并且会看到实际的回车符。

为什么 ASCII 中的第 13 个字符是 5E 4d 0a,即 ^M?

您在 echo "^M" 的输出上运行了 hexdump,它生成三个字符:^M > 和换行符 (LF)。请看上面,这与回车符不同!

为什么结束符0a显示为.? 。 DEC 中的 2E。十六进制数 5E 的 DEC 值是 94,4d 的 DEC 值是 77。

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 through sed '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 did echo $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 by M. While you see ^M, command line programs see only the raw data, and will see an actual carriage return character.

Why is 5E 4d 0a, ie ^M, 13th char in ASCII?

You ran hexdump on the output of echo "^M", which produces three characters: a ^, a M, and a linefeed character (LF). See above, that's not the same as a carriage return!

Why is the ending sign 0a shown as .? . is 2E in DEC. Hex number 5E is 94 in DEC, 4d is 77 in DEC.

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.

依 靠 2024-09-05 22:56:10

^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...

零度° 2024-09-05 22:56:10

如果您通过 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.

才能让你更想念 2024-09-05 22:56:10

帮助者问题的答案

我。为什么 5E 4d 0a,即 ^M,ASCII 中的第 13 个字符?

<块引用>

换行符是0a,请参见下面ZyX提供的示例。 rjh 澄清了有关第 13 个字符的内容。 echo -n 防止 echo 在其输出末尾添加换行符”。我正在使用 Debian。

$ echo "scale=20; $values[1]-$values[2]" |十六进制转储-C
00000000 73 63 61 6c 65 3d 32 30 3b 20 5b 31 5d 2d 5b 32 |规模= 20; [1]-[2|
00000010 5d 0a |].|
00000012
xyz@xyz:~$ echo -n "scale=20; $values[1]-$values[2]" |十六进制转储-C
00000000 73 63 61 6c 65 3d 32 30 3b 20 5b 31 5d 2d 5b 32 |规模= 20; [1]-[2|
00000010 5d |]|
00000011

二.为什么结尾符号“0a”显示为点“.”?这 ”。”十六进制的“2E”。

TODO:有人回答这个问题了吗?请发表评论、回答或编辑。

帮助示例的信息

ASCII 到 HEX

`.` 是十六进制的“2E”
`5E` 是十六进制的 `^` 
“4d”是十六进制的“M”

十六进制到 ASCII:使用它查看十六进制的含义

<前><代码>$ echo "^M" |十六进制转储-C
00000000 5e 4d 0a |^M.|
00000003
$ ASCII -x
0 NUL 10 DLE 20 30 0 40 @ 50 P 60 ` 70 p
1 SOH 11 DC1 21 ! 31 1 41 A 51 Q 61 A 71 Q
2 STX 12 DC2 22" 32 2 42 B 52 R 62 B 72 R
3 ETX 13 DC3 23#33 3 43C 53S 63C 73S
4 EOT 14 DC4 24 $ 34 4 44 D 54 T 64 d 74 t
5 ENQ 15 NAK 25 % 35 5 45 E 55 U 65 e 75 u
6 ACK 16 SYN 26 和36 6 46F 56V 66F 76V
7 BEL 17 ETB 27 ' 37 7 47 G 57 W 67 g 77 W
8 BS 18 CAN 28 ( 38 8 48 高 58 X 68 高 78 x
9 HT 19 EM 29 ) 39 9 49 I 59 Y 69 i 79 Y
A LF 1A SUB 2A * 3A : 4A J 5A Z 6A j 7A z
B VT 1B 电调 2B + 3B ; 4B K 5B [ 6B k 7B {
C FF 1C FS 2C , 3C < 4C L 5C \ 6C l 7C |
D CR 1D GS 2D - 3D = 4D M 5D ] 6D m 7D }
E SO 1E RS 2E 。 3E> 4E N 5E ^ 6E n 7E ~
F SI 1F 美国 2F / 3F ? 4F 或 5F _ 6F 或 7F 删除

Answers to Helper Questions

I. Why is 5E 4d 0a, ie ^M, 13th char in ASCII?

The newline is the 0a, please, see the example provided by ZyX below. rjh clarified something about the 13th char. The "echo -n prevents echo from adding a newline at the end of its output". I am using Debian.

$ echo "scale=20; $values[1]-$values[2]" | hexdump -C
00000000  73 63 61 6c 65 3d 32 30  3b 20 5b 31 5d 2d 5b 32  |scale=20; [1]-[2|
00000010  5d 0a                                             |].|
00000012
xyz@xyz:~$ echo -n "scale=20; $values[1]-$values[2]" | hexdump -C
00000000  73 63 61 6c 65 3d 32 30  3b 20 5b 31 5d 2d 5b 32  |scale=20; [1]-[2|
00000010  5d                                                |]|
00000011

II. Why is the ending sign "0a" shown as a dot "."? The "." is "2E" in Hex.

TODO: Did someone answer this already? Please, comment, answer or edit.

Information to help with the examples

ASCII to HEX

`.` is `2E` in Hex
`5E` is `^` in Hex 
`4d` is `M` in Hex

Hex to ASCII: use this see what the Hex -things mean

$ echo "^M" | hexdump -C
00000000  5e 4d 0a                                          |^M.|
00000003
$ ascii -x              
    0 NUL    10 DLE    20      30 0    40 @    50 P    60 `    70 p 
    1 SOH    11 DC1    21 !    31 1    41 A    51 Q    61 a    71 q 
    2 STX    12 DC2    22 "    32 2    42 B    52 R    62 b    72 r 
    3 ETX    13 DC3    23 #    33 3    43 C    53 S    63 c    73 s 
    4 EOT    14 DC4    24 $    34 4    44 D    54 T    64 d    74 t 
    5 ENQ    15 NAK    25 %    35 5    45 E    55 U    65 e    75 u 
    6 ACK    16 SYN    26 &    36 6    46 F    56 V    66 f    76 v 
    7 BEL    17 ETB    27 '    37 7    47 G    57 W    67 g    77 w 
    8 BS     18 CAN    28 (    38 8    48 H    58 X    68 h    78 x 
    9 HT     19 EM     29 )    39 9    49 I    59 Y    69 i    79 y 
    A LF     1A SUB    2A *    3A :    4A J    5A Z    6A j    7A z 
    B VT     1B ESC    2B +    3B ;    4B K    5B [    6B k    7B { 
    C FF     1C FS     2C ,    3C <    4C L    5C \    6C l    7C | 
    D CR     1D GS     2D -    3D =    4D M    5D ]    6D m    7D } 
    E SO     1E RS     2E .    3E >    4E N    5E ^    6E n    7E ~ 
    F SI     1F US     2F /    3F ?    4F O    5F _    6F o    7F DEL
别理我 2024-09-05 22:56:10

我通过从 ~/.gitconfig 中删除它来解决这个问题,

[core]
  autocrlf = true

由于某种原因,它会自动将 ^M 附加到我的 vim-plug 插件并破坏 neovim。

I fixed this by removing this from ~/.gitconfig

[core]
  autocrlf = true

Which was appending ^M to my vim-plug plugins automatically for some reason and breaking neovim.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文