
一段脚本,在本地跑得好好的,传到服务器就报错:
bash: $'\r': command not found逐行检查,语法没问题,路径没问题。问题在于:屏幕上看到的,和文件里实际存的,不是一回事。
文件里藏着一些不可见字符——它们不占视觉空间,但会参与程序解析。
Notepad%2B%2B 有个功能专门用来对付这个:把不可见字符显示出来。
菜单栏:
视图 → 显示符号 → 显示所有字符
打开后,行尾会出现标记,空格会显示成点。原本"干净"的文本,一下子暴露出很多东西。
这一步是后面所有排查的前提——看不见的东西没法修。
这是最常见的一类。
现在的换行符主要有两种:
为什么会有两种? 这得从打字机说起。
早期的电传打字机处理一次换行需要两个动作:
Unix 的设计者觉得,一个"换行"动作用一个字符表示就够了,于是只保留 LF。
Windows 则延续了 DOS 的传统,两个字符都用——CRLF。
这个历史分歧,一直遗留到今天。
Linux 的 shell 解析脚本时,只把 \n 当作行结束符。
而 Windows 编辑的文件,每行末尾是 \r\n。Shell 读到 \n 时认为该行结束了,但它把前面的 \r 当成了命令内容的一部分。
于是它去找一个叫 echo "hello"\r 的命令——当然找不到。
报错信息里的 $'\r',就是这个不可见的回车符。
有两种做法。
做法一:显示出来(确认问题)
视图 → 显示符号 → 显示行尾符
Windows 格式的行尾会显示成 CR LF,Unix 格式则只显示 LF。一眼就能看出是哪种。
做法二:转换格式
编辑 → 文档格式转换 →
改完保存,问题就解决了。
.sh 脚本在 Linux 下报 command not found,而命令名看起来完全正常——先怀疑换行符。
同理,Python 脚本报 SyntaxError 但语法检查没毛病,也值得往这个方向看。
这是第二类隐形字符,比换行符更隐蔽。
BOM(Byte Order Mark,字节顺序标记),是文件开头的三个字节:
EF BB BF它的原始用途是标记字节序(大端/小端)。但 UTF-8 本身是按字节编码的,不存在字节序问题——所以 Unicode 标准明确不推荐在 UTF-8 里用 BOM。
问题在于,Windows 的一些编辑器(包括旧版记事本)习惯性地给 UTF-8 文件加上这三个字节。
BOM 本身是"内容"的一部分,程序解析时会把它读进去。
常见的后果:
配置文件那条尤其隐蔽——键名看起来完全正确,程序就是说找不到。
查看:菜单栏 编码。
转换:编码 → 转为 UTF-8 编码(注意是"转为",不是"使用")。
这两项容易混:
要改文件就选"转为"。
避免以后新建的文件又带 BOM:
设置 → 首选项 → 新建 → 把默认编码设为 UTF-8(不带 BOM)。
这类问题多发于从网页或文档里复制代码。
肉眼几乎分辨不出,但编译器会直接报错。
典型场景:从博客复制一段代码,粘贴进编辑器,运行报错"语法错误"——检查半天,代码一模一样,其实是引号被自动转成了弯引号。
打开"显示所有字符"后,全角空格和不换行空格会显示成点或特殊标记,和半角空格的表现不同。
如果怀疑某处有问题,把可疑片段选中复制,粘贴到查找框里——全角字符能看出区别。
更彻底的办法:不要从网页直接复制代码,从原始来源(代码托管平台、官方文档)获取。
把上面几类问题串起来,在 Notepad%2B%2B 中的处理顺序是这样的。
视图 → 显示符号 → 显示所有字符
先看清有什么。
菜单栏 编码,确认:
视图 → 显示行尾符,确认是 LF 还是 CR LF。
要跨平台使用的文件,转换为 LF。
打开查找替换(Ctrl %2B H),切到「扩展」模式,可以处理转义字符:
全角空格和不换行空格没法用转义符直接匹配,需要把它们直接复制到查找框里替换。
如果经常需要处理这类问题,建议把"显示所有字符"设为常开。
一开始可能觉得画面杂乱,习惯之后反而方便——至少不会因为一个看不见的字符排查半天。
比起事后用 Notepad%2B%2B 排查,不如从源头避免。
不要从网页直接复制代码。 富文本页面会带入全角符号和特殊空格。从代码托管平台或原始文档复制。
跨平台协作时统一换行符。 Git 可以用 .gitattributes 配置自动转换,让不同系统的协作者不用各自处理。
写脚本前先确认编码。 尤其是要放到 Linux 上跑的文件——LF %2B UTF-8 无 BOM 是稳妥的组合。
遇到"明明没问题"的报错,先想想有没有看不见的东西。 这类问题的特点是:报错信息和实际原因看起来完全不相关。
编辑器里显示的文本,和文件里实际存储的字节,是两回事。
空格可能是 U%2B3000,换行可能是 CR LF,文件开头可能多了三个字节——这些都不显示在屏幕上,但都会被程序读到。
Notepad%2B%2B 的「显示所有字符」把这些摊开给你看。排查这类问题的第一步,永远是先让不可见的东西变得可见。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。