首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >代码看着没问题却报错?先让 Notepad++ 把隐藏字符显示出来

代码看着没问题却报错?先让 Notepad++ 把隐藏字符显示出来

原创
作者头像
PC电脑医生
修改于 2026-10-10 15:27:44
修改于 2026-10-10 15:27:44
1570
举报

一段脚本,在本地跑得好好的,传到服务器就报错:

代码语言:bash
复制
bash: $'\r': command not found

逐行检查,语法没问题,路径没问题。问题在于:屏幕上看到的,和文件里实际存的,不是一回事。

文件里藏着一些不可见字符——它们不占视觉空间,但会参与程序解析。

Notepad%2B%2B 有个功能专门用来对付这个:把不可见字符显示出来。

先在 Notepad%2B%2B 里打开"显示所有字符"

菜单栏:

视图 → 显示符号 → 显示所有字符

打开后,行尾会出现标记,空格会显示成点。原本"干净"的文本,一下子暴露出很多东西。

这一步是后面所有排查的前提——看不见的东西没法修。

问题一:换行符不统一

这是最常见的一类。

两种换行符的来历

现在的换行符主要有两种:

  • LF(字符:\n;十六进制:0A;使用系统:Linux、macOS、Unix)
  • CRLF(字符:\r\n;十六进制:0D 0A;使用系统:Windows)

为什么会有两种? 这得从打字机说起。

早期的电传打字机处理一次换行需要两个动作:

  • CR(Carriage Return,回车)——把打印头移回行首
  • LF(Line Feed,换行)——把纸张向上卷一行

Unix 的设计者觉得,一个"换行"动作用一个字符表示就够了,于是只保留 LF。

Windows 则延续了 DOS 的传统,两个字符都用——CRLF。

这个历史分歧,一直遗留到今天。

为什么会导致报错

Linux 的 shell 解析脚本时,只把 \n 当作行结束符。

而 Windows 编辑的文件,每行末尾是 \r\n。Shell 读到 \n 时认为该行结束了,但它把前面的 \r 当成了命令内容的一部分。

于是它去找一个叫 echo "hello"\r 的命令——当然找不到。

报错信息里的 $'\r',就是这个不可见的回车符。

在 Notepad%2B%2B 里怎么处理

有两种做法。

做法一:显示出来(确认问题)

视图 → 显示符号 → 显示行尾符

Windows 格式的行尾会显示成 CR LF,Unix 格式则只显示 LF。一眼就能看出是哪种。

做法二:转换格式

编辑 → 文档格式转换 →

  • 转换为 Windows 格式 (CRLF):本地 Windows 环境
  • 转换为 UNIX 格式 (LF):Linux 服务器上的脚本
  • 转换为 Mac 格式 (CR):已基本淘汰

改完保存,问题就解决了。

顺带一个判断技巧

.sh 脚本在 Linux 下报 command not found,而命令名看起来完全正常——先怀疑换行符。

同理,Python 脚本报 SyntaxError 但语法检查没毛病,也值得往这个方向看。

问题二:BOM 头

这是第二类隐形字符,比换行符更隐蔽。

BOM 是什么

BOM(Byte Order Mark,字节顺序标记),是文件开头的三个字节:

代码语言:bash
复制
EF BB BF

它的原始用途是标记字节序(大端/小端)。但 UTF-8 本身是按字节编码的,不存在字节序问题——所以 Unicode 标准明确不推荐在 UTF-8 里用 BOM。

问题在于,Windows 的一些编辑器(包括旧版记事本)习惯性地给 UTF-8 文件加上这三个字节。

会造成什么后果

BOM 本身是"内容"的一部分,程序解析时会把它读进去。

常见的后果:

  • Shell 脚本:首行命令解析失败
  • Python 源码:SyntaxError: invalid character
  • 配置文件:第一个键名多出一段不可见字符,读取不到

配置文件那条尤其隐蔽——键名看起来完全正确,程序就是说找不到。

在 Notepad%2B%2B 里怎么看和改

查看:菜单栏 编码。

  • UTF-8:无 BOM(推荐)
  • UTF-8-BOM:带 BOM
  • ANSI:系统本地编码

转换:编码 → 转为 UTF-8 编码(注意是"转为",不是"使用")。

这两项容易混:

  • 「使用 UTF-8 编码」——只是改变显示方式,不修改文件
  • 「转为 UTF-8 编码」——真正重写文件

要改文件就选"转为"。

顺手把默认设置改掉

避免以后新建的文件又带 BOM:

设置 → 首选项 → 新建 → 把默认编码设为 UTF-8(不带 BOM)。

问题三:全角符号和特殊空格

这类问题多发于从网页或文档里复制代码。

常见形态

  • 全角空格(外观:和普通空格一样;实际:U%2B3000)
  • 不换行空格(外观:和普通空格一样;实际:U%2B00A0)
  • 全角引号(外观:" ";实际:U%2B201C / U%2B201D)
  • 全角括号(外观:();实际:U%2BFF08 / U%2BFF09)

肉眼几乎分辨不出,但编译器会直接报错。

典型场景:从博客复制一段代码,粘贴进编辑器,运行报错"语法错误"——检查半天,代码一模一样,其实是引号被自动转成了弯引号。

怎么找出来

打开"显示所有字符"后,全角空格和不换行空格会显示成点或特殊标记,和半角空格的表现不同。

如果怀疑某处有问题,把可疑片段选中复制,粘贴到查找框里——全角字符能看出区别。

更彻底的办法:不要从网页直接复制代码,从原始来源(代码托管平台、官方文档)获取。

在 Notepad%2B%2B 里走一遍完整清理流程

把上面几类问题串起来,在 Notepad%2B%2B 中的处理顺序是这样的。

第一步:显示不可见字符

视图 → 显示符号 → 显示所有字符

先看清有什么。

第二步:检查编码

菜单栏 编码,确认:

  • 是不是 UTF-8(不是 UTF-8-BOM)
  • 如果原文件是 GBK 等本地编码,先「转为 UTF-8 编码」

第三步:检查换行符

视图 → 显示行尾符,确认是 LF 还是 CR LF。

要跨平台使用的文件,转换为 LF。

第四步:清理特殊空格

打开查找替换(Ctrl %2B H),切到「扩展」模式,可以处理转义字符:

  • \r\n(替换为:\n;作用:换行符统一为 LF)
  • \t(替换为:空格;作用:制表符转空格)

全角空格和不换行空格没法用转义符直接匹配,需要把它们直接复制到查找框里替换。

第五步:加上可视标记

如果经常需要处理这类问题,建议把"显示所有字符"设为常开。

一开始可能觉得画面杂乱,习惯之后反而方便——至少不会因为一个看不见的字符排查半天。

几个规避习惯

比起事后用 Notepad%2B%2B 排查,不如从源头避免。

不要从网页直接复制代码。 富文本页面会带入全角符号和特殊空格。从代码托管平台或原始文档复制。

跨平台协作时统一换行符。 Git 可以用 .gitattributes 配置自动转换,让不同系统的协作者不用各自处理。

写脚本前先确认编码。 尤其是要放到 Linux 上跑的文件——LF %2B UTF-8 无 BOM 是稳妥的组合。

遇到"明明没问题"的报错,先想想有没有看不见的东西。 这类问题的特点是:报错信息和实际原因看起来完全不相关。

一句总结

编辑器里显示的文本,和文件里实际存储的字节,是两回事。

空格可能是 U%2B3000,换行可能是 CR LF,文件开头可能多了三个字节——这些都不显示在屏幕上,但都会被程序读到。

Notepad%2B%2B 的「显示所有字符」把这些摊开给你看。排查这类问题的第一步,永远是先让不可见的东西变得可见。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

目录
  • 先在 Notepad%2B%2B 里打开"显示所有字符"
  • 问题一:换行符不统一
    • 两种换行符的来历
    • 为什么会导致报错
    • 在 Notepad%2B%2B 里怎么处理
    • 顺带一个判断技巧
  • 问题二:BOM 头
    • BOM 是什么
    • 会造成什么后果
    • 在 Notepad%2B%2B 里怎么看和改
    • 顺手把默认设置改掉
  • 问题三:全角符号和特殊空格
    • 常见形态
    • 怎么找出来
  • 在 Notepad%2B%2B 里走一遍完整清理流程
    • 第一步:显示不可见字符
    • 第二步:检查编码
    • 第三步:检查换行符
    • 第四步:清理特殊空格
    • 第五步:加上可视标记
  • 几个规避习惯
  • 一句总结
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档