Windows BAT批处理由于CRLF问题引发的奇怪错误
问题非常奇怪,基本的日志输出都会出错,代码如下:
1. 问题非常奇怪,基本的日志输出都会出错
代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
13@echo off
setlocal enabledelayedexpansion
:: 获取当前日期和时间,格式可能因系统区域设置而异
set "currentTime=%date% %time%"
:: 替换日期和时间格式中的特殊字符(如果需要)
set "currentTime=!currentTime:/=-!"
:: 输出当前时间加上消息内容到文件,如果文件不存在则创建
echo [!currentTime!] 这是你的消息内容 >> output.log
endlocal代码没有什么功能实现,只是简单的输出日志到文件
运行结果:
1 | $ ./speed-starter.bat |
奇怪的错误,完全看不出问题的原因
2. 问题解决
对于这个问题简直是毫无头绪,检测语法完全没有问题。最后为了确认语法没问题,使用VSCode新建另外一个代码内容完全一样的Bat文件:start.bat
1 | @echo off |
运行发现没有任何错误,日志也输出到了 output.log
于是重新运行之前的 starter.bat 还是相同的错误!这就奇怪了!
为了验证两个文件的差别,用 VSCode 同时左右分屏打开,代码内容确实完全一样!还是毫无头绪。
最终不经意注意到了 VSCode 在切换两个文件时,右下角的状态栏由变化:
- starter.bat -> LF
- start.bat -> CRLF
CRLF 我以前有了解过,就是不同操作系统对文本文件的换行符号有所不同,Windows 下的换行是 \r\n
,也叫回车换行,对应 CRLF
。
所以 starter.bat 只有 LF
没有 RC
,脚本解释器把所有代码都认为在同一行执行,出错时当然的了!
所以解决办法就是把 LF
切换到 CRLF
模式。这得借助 VSCode 或者 IDEA 这样的高级编辑器,记事本估计不行。
3. CRLF 知识补课
CRLF是“Carriage Return Line Feed”的缩写,它表示回车换行,对应的ASCII码是“\r\n”。
关于CRLF,以及不同操作系统之间的差异,以下是一些相关知识:
- CR、LF与CRLF的含义与起源:
- CR(Carriage Return,回车):对应ASCII中的转义字符’\r’,其十进制ASCII代码是13,十六进制代码为0x0D。在机械打字机时代,CR的作用是将打字机上的滚动托架(Carriage)滚回到打印纸张的最左侧,但保持当前打字的垂直位置不变,即还是在同一行。
- LF(Line Feed,换行):对应ASCII中的转义字符’\n’,其ASCII代码是10,十六进制为0x0A。LF的作用是将打印纸张上移一行位置,但保持当前打字的水平位置不变。
- CRLF:即CR+LF,表示回车并换行,对应的ASCII码是“\r\n”。
- 不同操作系统中的换行符差异:
Windows系统:采用CRLF(\r\n)表示回车换行。这意味着在Windows平台上,换行在文本文件中是使用两个字节(0d 0a)来表示的。
Unix/Linux系统:采用LF(\n)表示换行。在Unix/Linux系统中,每行的末尾只有newline(即“\n”),换行符由0a一个字节表示。
Mac系统:早期的Mac OS系统(如MacIntosh)采用CR(\r)表示回车作为换行;而现代的Mac OS X系统则与其他 Unix-like 系统一样,采用LF(\n)作为换行符。
- 换行符差异的影响:这种差异在文本编辑和跨平台软件开发中可能会导致问题。例如,当代码开发者在不同的系统上都编辑过同一份代码并来回传输时,或者当多人协作开发一个项目并使用版本控制系统(如git)进行源码管理时,就可能会出现换行符不统一的问题。这可能会导致代码在不同系统上的表现不一致,或者在版本控制系统中产生不必要的差异。
- 本文作者:scwang90
- 本文链接:https://blog.scwang90.cn/2024/03/30/bat-crlf/index.html
- 版权声明:本分享所有文章均采用 BY-NC-SA 许可协议,转载请注明出处!