在macOS中替换Windows换行符CRLF

背景

所谓的CR也就是“回车”(Carriage Return,\r),LF就是“换行”(Line Feed,\n)。顾名思义,回车就是把光标移到行首,换行就是新增一行。众所周知Windows下的用的是\r\n,unix下的用的是\n,以前的mac用的是\r,但也早已投入\n的怀抱。历史原因在此不表,主要说说怎么在macOS下把\r\n转换成\n。

解决办法

在Linux下做这个转换是非常简单的,只需要:

1
sed -i 's/\r//g' file

如果系统自带dos2unix就更简单了:

1
dos2unix file

但是macOS既不带dos2unix,sed处理方式也和Linux不同。因为Linux用的是GNU版sed,而macOS用的BSD版sed。

首先是macOS下的sed要替换源文件,需要在-i参数后面还需要加空字符串:

1
sed -i '' 's/\r//g' file

但你会发现在替换其他字符的时候是有效的,对于\r根本不起作用。因为macOS下的sed并不把\r当作特殊字符处理。

实际上,你需要这样使用才可以替换\r:

1
sed -i '' $'s/\r//' file

具体的原因可以参考man bash里面的$'string'的说明

或者你也可以这样:

1
sed -i '' "s/$(printf '\r')//" file

也可以用ASCII码:

1
sed -i '' $'s/\x0D//' file

用tr会更简单一点:

1
tr -d '\r' < file > new_file

编码问题

在一般情况下,上面的命令就能成功执行了。但是你也许也会像我一样碰到另一个错误:

1
sed: RE error: illegal byte sequence

这是由于编码原因导致的,可以通过在sed命令前加LC_ALL=C解决:

1
LC_ALL=C sed -i '' $'s/\r//' file

tr也是一样的:

1
LC_ALL=C tr -d '\r' < file > new_file

补充

其实macOS下也可以安装GNU版本的sed:

1
brew install gsed

也可以安装dos2unix:

1
brew install dos2unix

使用cat -v命令可以看到不可见字符(\r会显示为^M)

1
cat -v file

参考

https://stackoverflow.com/questions/21621722/removing-carriage-return-on-mac-os-x-using-sed

https://stackoverflow.com/questions/19242275/re-error-illegal-byte-sequence-on-mac-os-x