knot22 Asked: 2023-04-13 04:13:46 +0800 CST2023-04-13 04:13:46 +0800 CST 2023-04-13 04:13:46 +0800 CST 在每个 LF 之前添加一个 CR 772 我有一个正在 Windows 机器上处理的文本文件。bcp在使用实用程序将数据从文件加载到数据库表之前,需要删除尾随的制表符。 以下命令在 Bash 脚本中删除了尾随的制表符: sed 's/[\t]*$//' < ./input/raw.txt >> ./input/data.txt CR但它将-转换LF为LF导致bcp命令失败的原因。 为了保持CR-LF我试过这个: sed 's/[\t]*$/$CR/' < ./input/raw.txt >> ./input/data.txt 但这导致: 期望的结果是: 如何修改命令以获得所需的输出? bash 3 个回答 Voted Jim L. 2023-04-13T04:22:40+08:002023-04-13T04:22:40+08:00 您需要安装该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 Best Answer Stéphane Chazelas 2023-04-13T04:22:16+08:002023-04-13T04:22:16+08:00 请注意,在标准中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 都支持它,并将出现在sh. 如果你在 shell 变量中有 TAB 和 CR 字符,你可以不用它们,$'...'例如: eval "$(printf 'TAB="\t" CR="\r"')" 你可以这样做: sed "s/$TAB*\$/$CR/" 但这必须在双引号内。在单引号内,不执行扩展。 现在,万一输入不以 LF 字符结尾(这会使它在 Unix 中成为无效文本),那些(至少在 GNU 中)会生成一个以 CR 字符结尾的文件,使其sed在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且仅在正则表达式中),并且可以处理非文本文件。 jubilatious1 2023-04-17T19:13:53+08:002023-04-17T19:13:53+08:00 使用Raku(以前称为 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在内部使用 -terminated 换行符,并nl-out为文件句柄输出提供了一个参数(默认为"\n")。 OP的关键声明如下: ...但它转换CR-LF为LFwhich 导致 bcp 命令失败。 因此,对于上面的 Raku 脚本(在您正在使用的任何平台上),您可以打开一个文件进行写入并设置nl-out => \r\n,即换行符输出到 CRLF。Rakulines懒惰地阅读,所以这个脚本应该是内存高效的。即使不使上述脚本可执行,您也可以在命令行中调用它,如下所示: ~$ raku unix2dos.raku < ends_with_LF.txt > ends_with_CRLF.txt 上面的脚本默认采用$*INstdin,因此是“一次性的”,但 Raku 也提供读取$*ARGFILES和dir目录功能。最后,在下面的第一个链接中有关于 Raku 中换行处理的精彩总结: https://docs.raku.org/language/newline.html https://raku.org
您需要安装该
unix2dos
软件包。它有两个实用程序:让我们创建一个包含五行的测试文件,并进行十六进制转储来检查行尾:
我们看到每一行都以换行符结尾,十六进制 0a。
现在我们将这些换行符转换为 DOS CR-LF 行尾,并再次检查:
现在每一行都以 CR-LF,十六进制 0d 0a 结尾。
最后,我们可以将文件转换回原始的 UNIX 换行符:
请注意,在标准中
sed
,从行尾sed 's/[\t]*$//'
删除所有反斜杠和字符。t
的 GNU 实现sed
仅在其环境中存在POSIXLY_CORRECT
变量时才执行此操作。sed 's/\t*$//'
未指定,但至少在 GNU 中,无论是否在环境中,sed
它都会删除尾随的 TAB 。POSIXLY_CORRECT
在这里你可以这样做:
使用 ksh93 样式
$'...'
的引号形式,其中类似\t
或的内容\r
分别扩展为 TAB 和 CR。现在许多其他 shell 都支持它,并将出现在sh
.如果你在 shell 变量中有 TAB 和 CR 字符,你可以不用它们,
$'...'
例如:你可以这样做:
但这必须在双引号内。在单引号内,不执行扩展。
现在,万一输入不以 LF 字符结尾(这会使它在 Unix 中成为无效文本),那些(至少在 GNU 中)会生成一个以 CR 字符结尾的文件,使其
sed
在DOS 也一样。要将文本文件从 Unix 转换为 DOS,您可以使用
unix2dos
不会有问题的实用程序:或者使用
perl
的sed
模式:perl -p
工作方式类似于sed
它为每一行输入运行代码,除了在perl
模式空间($_
那里)中有完整的行,包括行定界符。它还支持那些\t
,\n
,\r
转义符(而标准sed
仅支持\n
且仅在正则表达式中),并且可以处理非文本文件。使用Raku(以前称为 Perl_6)
Raku(又名 Perl6)是 Perl 家族中的一种编程语言。Perl6 项目试图做的一件事是抽象出特定于操作系统的问题以使代码更具可移植性,而这些问题之一就是换行处理。Raku
nl-in
为文件句柄输入提供了一个参数(默认为["\x0A", "\r\n"]
),默认自动切换行,\n
在内部使用 -terminated 换行符,并nl-out
为文件句柄输出提供了一个参数(默认为"\n"
)。OP的关键声明如下:
因此,对于上面的 Raku 脚本(在您正在使用的任何平台上),您可以打开一个文件进行写入并设置
nl-out => \r\n
,即换行符输出到 CRLF。Rakulines
懒惰地阅读,所以这个脚本应该是内存高效的。即使不使上述脚本可执行,您也可以在命令行中调用它,如下所示:上面的脚本默认采用
$*IN
stdin,因此是“一次性的”,但 Raku 也提供读取$*ARGFILES
和dir
目录功能。最后,在下面的第一个链接中有关于 Raku 中换行处理的精彩总结:https://docs.raku.org/language/newline.html
https://raku.org