Mac 自带 sed 怎么转 \r\n 为 \n?(dos换行转unix)

需要把 \r\n 转成 \n,最近学过 sed,看看它有什么解法。

man sed 显示,Mac 自带的 sed 非常老旧,来自 2005 年的 FreeBSD。

第一种解法 sed 's/\r//' ,没用

~ $ printf '\r\n' | hexdump -C
00000000  0d 0a                                             |..|
00000002

~ $ printf '\r\n' | sed 's/\r//' | hexdump -C
00000000  0d 0a                                             |..|
00000002

~ $ printf '\r\n' | sed -E 's/\r//' | hexdump -C
00000000  0d 0a                                             |..|
00000002

它的正则表达式到底怎么表示 \r?试过 \x0d 也不行。

gnu 版本是可以的,但是不考虑,要自己单独装

~ $ printf '\r\n' | gsed -E 's/\r//' | hexdump -C
00000000  0a                                                |.|
00000001

第二种解法手打 ^M ,不好

Zsh 里 C-v C-m 或者 Emacs 里 C-q C-m,一是手打麻烦,需要记忆,二是直接插入脚本里不美观

第三种解法 sed s/.$//,可行但不完美

它的前提是每一行都是以 \r\n 结尾,我觉得还是测试下更加安全。

必须 sed ?

sed 处理这个有点麻烦,我一般用 tr

比如:

printf '\r\n' | tr -d '\r' | hexdump -C
00000000  0a                                                |.|
00000001

(不过这是 Linux 测试结果

需要了解下 Sed 的用法,毕竟在它的能力范围之内,还有 Tab 也不清楚怎么表示,\t 没用

~ $ printf "a\tb\n" | sed 's/\t//'
a	b
$ man sed | head -2

SED(1)                    BSD General Commands Manual                   SED(1)

$ printf '\r\n' | sed $'s/\r//' | hexdump -C
00000000  0a                                                |.|
00000001
1赞

学到了,$'string'(info “(bash) ANSI-C Quoting”),试了下 ZSH 和 ASH 都支持,

不知道是不是 POSIX sh 规定,没规定:

1赞

感觉这是个原本 Shell 问题:

# 打印字符串是 JS 写法
~ $ my-print-args 's/\r//'
[ 's/\\r//' ]
~ $ my-print-args $'s/\r//'
[ 's/\r//' ]

所以说 GNU Sed 支持了把 \\r 当成 \r,但 macOS Sed 不支持。

自带的限制太多。。我都是用 brew 的 gsed