如何以编程方式(不使用vi)将DOS/Windows换行符转换为Unix换行符?

dos2unix和unix2dos命令在某些系统上不可用。 如何使用sed、awk和tr等命令模拟它们?


当前回答

有趣的是,在Windows上的Git Bash中,sed ""已经做到了:

$ echo -e "abc\r" >tst.txt
$ file tst.txt
tst.txt: ASCII text, with CRLF line terminators
$ sed -i "" tst.txt
$ file tst.txt
tst.txt: ASCII text

我的猜测是,sed在从输入读取行时忽略它们,并且总是将Unix行结束符写入输出。

其他回答

The solutions posted so far only deal with part of the problem, converting DOS/Windows' CRLF into Unix's LF; the part they're missing is that DOS use CRLF as a line separator, while Unix uses LF as a line terminator. The difference is that a DOS file (usually) won't have anything after the last line in the file, while Unix will. To do the conversion properly, you need to add that final LF (unless the file is zero-length, i.e. has no lines in it at all). My favorite incantation for this (with a little added logic to handle Mac-style CR-separated files, and not molest files that're already in unix format) is a bit of perl:

perl -pe 'if ( s/\r\n?/\n/g ) { $f=1 }; if ( $f || ! $m ) { s/([^\n])\z/$1\n/ }; $m=1' PCfile.txt

注意,这将把文件的统一版本发送到标准输出。如果你想用一个统一的版本替换这个文件,添加perl的-i标志。

这是超级duper容易与PCRE;

作为脚本,或者用文件替换$@。

#!/usr/bin/env bash
perl -pi -e 's/\r\n/\n/g' -- $@

这将覆盖您的文件! 我建议只在备份时这样做(版本控制或其他方式)

一个更简单的没有程序的AWK解决方案:

awk -v ORS='\r\n' '1' unix.txt > dos.txt

从技术上讲,“1”是您的程序,因为AWK在给定选项时需要一个。

或者,内部解决方案是:

while IFS= read -r line;
do printf '%s\n' "${line%$'\r'}";
done < dos.txt > unix.txt

使用AWK你可以做到:

awk '{ sub("\r$", ""); print }' dos.txt > unix.txt

使用Perl你可以做到:

perl -pe 's/\r$//' < dos.txt > unix.txt

对于Mac OS X,如果您安装了Homebrew (http://brew.sh/):)

brew install dos2unix

for csv in *.csv; do dos2unix -c mac ${csv}; done;

确保您已经复制了文件,因为这个命令将在适当的位置修改文件。 -c mac选项使开关与OS X兼容。