如何处理 CRLF、CR 行结尾

如何处理 CRLF、CR 行结尾

我有一个 Perl 脚本,可以解析从多个学区发送给我的数据。我要添加一所新学校,但遇到了以前从未遇到过的问题。当我这样做时$line = <INPUT>,它会吞掉整个文件而不是一行。

如果我运行file该文件,它会返回UTF-8 Unicode text, with CRLF, CR line terminators.我的所有其他文件都返回ASCII text, with CRLF line terminators。我已经通过 dos2unix 运行它,但它仍然作为一个长字符串运行。当我在 emacs 中编辑它时,它仍然显示 ^M 作为行结尾。

我该如何将这些行结尾转换为可用的行结尾?

更新:供应商向我发送了另一个具有不同行结尾的文件,但仍然不起作用。它们报告为 CRLF、LF。我提取了一个几个样本行

以下是我的代码的一些片段:

$line = <INPUT> if ($schooldistricts{$schooldistrict}{'header'});
LINE: foreach $line (<INPUT>) {
    next LINE unless ($line =~ /\S/);
    <do stuff>
}

该文件确实有一个被正确剥离的标头。然后在 foreach 循环中,它成功读取第一行,然后就这样了——就像文件的其余部分是空的一样。

我尝试设置$/\r\n\n,但脚本什么也没做。如果我尝试的话也一样\r\n。有没有办法明确地查看行结尾编码了哪些字符?

第二次更新:作为实验,我将文件导入 Excel,将其拆分,并将其另存为制表符分隔文件。在服务器上,我运行dos2unix。 Perl 脚本在第二行之后仍然无法解析。File现在返回UTF-8 Unicode text, with CRLF line terminators。这是正确的行结尾,因此 Unicode 成为问题。 Unicode 对行结尾的编码方式有什么不同吗?

答案1

perl -pi -e 's/\r\n?/\n/g' your-file

将 CR 字符(可选择后跟 LF)转换为 LF,类似于mac2unixdos2unix -c mac的操作。

或者:

perl -pi -e 's/\r\n?/\r\n/g' your-file

如果这是您的脚本所期望的,则将它们转换为 CRLF(因为例如它将$/输入记录分隔符设置为"\r\n")。

答案2

该管道会将 CR 字符或 CR/LF 序列转换为 LF

tr '\r\n' '\n\r' | sed 's/^\r//g' | tr '\r' '\n'

答案3

使用(以前称为 Perl_6)

如果 OP 认为问题是基于 Unicode 的,那么通过 Raku 脚本可能会有所帮助,因为 Raku 默认处理 UTF-8:

~$ cat dos2unix.raku
my $fh1 = open $*IN, :r;

#below use :w (write-only) or :x (:x write-only :exclusive i.e. 'no-clobber')
my $fh2 = open $*OUT, :x, nl-out => "\n";

for $fh1.lines() { $fh2.put($_) };

$fh1.close;
$fh2.close;

将上述文件保存到脚本中(例如“dos2unix.raku”),添加 shebang 行并使其可执行 - 或者只需在命令行中调用它:

~$ raku dos2unix.raku < ends_with_CRLF.txt > ends_with_LF.txt 

带有 DOS 行结尾的示例输入(0d 0a每行):

~$ jot -w '%d' 5 | raku unix2dos.raku | hexdump -C
00000000  31 0d 0a 32 0d 0a 33 0d  0a 34 0d 0a 35 0d 0a     |1..2..3..4..5..|

示例输出转换为 Unix 行结尾(0a每行):

~$ jot -w '%d' 5 | raku unix2dos.raku | raku dos2unix.raku | hexdump -C
00000000  31 0a 32 0a 33 0a 34 0a  35 0a                    |1.2.3.4.5.|
0000000a

上面复制了真实的 Unix 行结尾(0a每行):

~$ jot -w '%d' 5 | hexdump -C
00000000  31 0a 32 0a 33 0a 34 0a  35 0a                    |1.2.3.4.5.|
0000000a

如果上面的脚本不起作用,那么正则表达式解决方案可能对slurped 文件有帮助(\v代表垂直空白)。 Raku 声称尊重 Raku Regex 方言中行边界的 Unicode 定义: https://unicode.org/reports/tr18/#Line_Boundaries

~$ raku -e 'slurp.subst(:global, / \v /, "\n").chop.put;'  file

#OR

~$ raku -e 'slurp.subst(:global, / <+ :Zl + :Zp> /, "\n").chop.put;'  file

请参阅下面的第一个链接的脚本unix2dos.raku(即相反的答案)。

参考:
https://unix.stackexchange.com/a/743445/227738
https://docs.raku.org/language/newline.html
https://raku.org

示例来源:
https://unix.stackexchange.com/a/742732/227738

相关内容