问题:我在Windows和*nix上都生成了数据(主要是CSV格式),主要在*nix上处理.Windows使用CRLF进行行结束,Unix使用LF.对于任何特定文件,我不知道它是否有窗口或*nix行结尾.到目前为止,我一直在写这样的东西来处理差异:
while (<$fh>){
tr/\r\n//d;
my @fields = split /,/, $_;
# ...
}
Run Code Online (Sandbox Code Playgroud)
在*nix上,\n部分相当于chomping,如果是windows生成的文件,则另外删除\ r \n(CR).
但是现在我想要Text :: CSV_XS b/c我开始使用带引号的数据获取更奇怪的数据文件,可能还有嵌入式换行符等.为了让这个模块读取这些文件,Text :: CSV_XS: :getline()要求您指定行尾字符.(我无法读取上面的每一行,tr/\n\r // d,然后用Text :: CSV b/c解析它不能正确处理嵌入式换行符).如何正确检测任意文件是否使用windows或*nix样式行结尾,所以我可以告诉Text :: CSV_XS :: eol()如何chomp()?
我在CPAN上找不到简单检测行结尾的模块.我不想首先通过dos2unix转换我的所有数据文件,b/c文件很大(数百千兆字节),并且每个文件花费10多分钟来处理这么简单的事情似乎很愚蠢.我想过编写一个函数来读取文件的前几百个字节并计算LF和CRLF,但我拒绝相信这没有更好的解决方案.
有帮助吗?
注意:所有文件要么具有完全的Windows行结尾,要么具有*nix结尾,即它们不会混合在一个文件中.
你可以使用刚刚打开文件:crlf PerlIO的层,然后告诉文本:: CSV_XS使用\n作为行结束字符.这将静默地将任何CR/LF对映射到单行换行,但这可能是您想要的.
use Text::CSV_XS;
my $csv = Text::CSV_XS->new( { binary => 1, eol => "\n" } );
open( $fh, '<:crlf', 'data.csv' ) or die $!;
while ( my $row = $csv->getline( $fh ) ) {
# do something with $row
}
Run Code Online (Sandbox Code Playgroud)
从Perl 5.10开始,您可以使用它来检查一般的行尾,
s/\R//g;
Run Code Online (Sandbox Code Playgroud)
它应该适用于*nix和Windows的所有情况.