如何移除流末尾的最后一个换行符(适配macOS命令行)
解决macOS命令行移除流末尾换行符的问题
我太懂这种困扰了!macOS自带的BSD工具和Linux上的GNU工具确实有不少行为差异,导致你之前的sed命令没法覆盖所有场景。下面给你几个实用的解决方案,不管是单个末尾换行还是多个空行结尾的情况都能搞定,而且都是macOS默认自带的工具,不用额外安装:
方案1:用Perl(最简洁通用)
Perl的语法在macOS上和Linux一致,这个命令能一次性移除所有末尾的换行符,不管有多少个:
# 测试单个末尾换行的情况 printf $'line 1\nline 2\n' | perl -0777 -pe 's/\n+$//' # 测试多个末尾空行的情况 printf $'line 1\nline 2\n\n' | perl -0777 -pe 's/\n+$//'
原理:-0777让Perl一次性读取整个输入流(而非逐行处理),然后用正则s/\n+$//匹配并替换掉所有末尾的换行符,完美覆盖两种场景。
方案2:用Awk(跨平台兼容性强)
Awk也是macOS自带的工具,这个脚本会处理每一行内容,最后用printf输出最后一行(不带换行),自动忽略末尾的空行:
printf $'line 1\nline 2\n\n' | awk '{if (NR>1) print prev; prev=$0} END{printf "%s", prev}'
原理:用prev变量缓存上一行内容,除第一行外,每到新行就打印缓存的内容;最后在END块里用printf输出最后一行(不会自动加换行),这样不管末尾有多少空行,都会被过滤掉,只保留有效内容的最后一行且不带换行。
方案3:改进版Sed(仅用Sed解决)
如果你只想用Sed,那需要适配BSD Sed的语法,这个命令能读取全部内容后移除末尾所有换行:
printf $'line 1\nline 2\n' | sed -n '1h;1!H;${g;s/\n*$//p;}'
原理:
1h:把第一行内容存入保持空间1!H:把后续每一行追加到保持空间(保留换行)${g;s/\n*$//p;}:到最后一行时,将保持空间的内容复制到模式空间,替换掉末尾所有换行符,然后打印结果
这三个方案都能完美解决你遇到的问题,根据自己的习惯选就行~
内容的提问来源于stack exchange,提问作者doekman
相关产品推荐
相关产品推荐

