答案1
您需要安装该unix2dos
软件包。它有两个实用程序:
unix2dos Convert UNIX newlines to CR-LF
dos2unix Convert DOS CR-LF to UNIX newlines
让我们创建一个包含五行的测试文件,并执行十六进制转储来检查行结尾:
$ jot -w 'line %d' 5 > foo
$ hexdump -C foo
00000000 6c 69 6e 65 20 31 0a 6c 69 6e 65 20 32 0a 6c 69 |line 1.line 2.li|
00000010 6e 65 20 33 0a 6c 69 6e 65 20 34 0a 6c 69 6e 65 |ne 3.line 4.line|
00000020 20 35 0a | 5.|
00000023
我们看到每一行都以换行符(十六进制 0a)结尾。
现在我们将这些换行符转换为 DOS CR-LF 行尾,然后再次检查:
$ unix2dos foo
$ hexdump -C foo
00000000 6c 69 6e 65 20 31 0d 0a 6c 69 6e 65 20 32 0d 0a |line 1..line 2..|
00000010 6c 69 6e 65 20 33 0d 0a 6c 69 6e 65 20 34 0d 0a |line 3..line 4..|
00000020 6c 69 6e 65 20 35 0d 0a |line 5..|
00000028
现在每行以 CR-LF 结束,十六进制 0d 0a。
最后,我们可以将文件转换回原始的 UNIX 换行符:
$ dos2unix foo
$ hexdump -C foo
00000000 6c 69 6e 65 20 31 0a 6c 69 6e 65 20 32 0a 6c 69 |line 1.line 2.li|
00000010 6e 65 20 33 0a 6c 69 6e 65 20 34 0a 6c 69 6e 65 |ne 3.line 4.line|
00000020 20 35 0a | 5.|
00000023
答案2
请注意,在标准中sed
,删除行尾的sed 's/[\t]*$//'
所有反斜杠和字符。 t
GNU 实现仅在其环境中sed
存在变量时才执行此操作。POSIXLY_CORRECT
sed 's/\t*$//'
未指定,但至少对于 GNU 来说,无论是否在环境中,sed
都会删除尾随的 TAB 。POSIXLY_CORRECT
在这里你可以这样做:
sed $'s/\t*$/\r/'
使用 ksh93 样式$'...'
的引号形式,其中类似\t
或 的内容\r
分别扩展为 TAB 和 CR。现在许多其他 shell 都支持这一点,并且将出现在 POSIX 标准的下一版本中sh
。
如果 shell 变量中有 TAB 和 CR 字符,则可以不使用这些字符,$'...'
例如:
eval "$(printf 'TAB="\t" CR="\r"')"
你可以这样做:
sed "s/$TAB*\$/$CR/"
但它必须在双引号内。在单引号内,不执行扩展。
现在,万一输入不以 LF 字符结尾(这将使其在 Unix 中成为无效文本),那些(sed
至少对于 GNU)将生成一个以 CR 字符结尾的文件,使其在 Unix 中无效。 DOS也是如此。
要将文本文件从 Unix 转换为 DOS,您可以使用该unix2dos
实用程序,这样就不会出现问题:
sed $'s/\t*$//' | unix2dos
或者使用perl
的sed
模式:
perl -pe 's/\t*$//; s/\n/\r\n/'
perl -p
其工作原理类似于sed
它为每行输入运行代码,只不过在perl
模式空间($_
那里)具有包含行分隔符的整行。它还支持那些\t
, \n
,\r
转义符(而标准sed
仅支持\n
且仅在正则表达式中),并且可以处理非文本文件。
答案3
使用乐(以前称为 Perl_6)
~$ cat unix2dos.raku
my $fh1 = open $*IN, :r;
#below :x opens write-only :exclusive (i.e. 'no-clobber')
my $fh2 = open $*OUT, :x, nl-out => "\r\n";
for $fh1.lines() { $fh2.put($_) };
$fh1.close;
$fh2.close;
Raku(又名 Perl6)是 Perl 家族中的一种编程语言。 Perl6 项目试图做的一件事是抽象出操作系统特定的问题,使代码更可移植,而这些问题之一就是换行处理。 Rakunl-in
为文件句柄输入提供一个参数(默认为["\x0A", "\r\n"]
),默认情况下自动剪切行,\n
在内部使用 - 终止换行符,并nl-out
为文件句柄输出提供一个参数(默认为"\n"
)。
OP的关键声明如下:
...但是它将 转换
CR-LF
为LF
导致 bcp 命令失败。
因此,对于上面的 Raku 脚本(在您正在使用的任何平台上),您可以打开一个文件进行写入并设置nl-out => \r\n
,即换行符为 CRLF。 Raku 读取lines
缓慢,因此该脚本应该节省内存。即使没有使上述脚本可执行,您也可以在命令行中调用它,如下所示:
~$ raku unix2dos.raku < ends_with_LF.txt > ends_with_CRLF.txt
上面的脚本默认采用$*IN
stdin,因此是“一次性”的,但 Raku也提供了读取$*ARGFILES
和目录功能。dir
最后,下面的第一个链接对 Raku 中的换行处理进行了精彩的总结:
https://docs.raku.org/language/newline.html
https://raku.org