作者liyih ()
看板Perl
标题Re: [问题] Perl读档 in Windows
时间Mon Mar 21 14:08:56 2011
试一下下面的 code,就可以看出 $/ ($INPUT_RECORD_SEPARATOR) 对於
换行的影响,也就是逐行读入的差别所在。如果要读的档案不确定是用
何种换行符号,或是都存在各种换行符号,那麽可以考虑用 slurp mode
都读进来後再处理。这个问题也很常见於写一些网路应用程式,建议可以
参考 Net::Cmd 模组 getline() 函式。
my @buf = split(/\015?\012/, $buf, -1); ## break into lines
=================================================================
#!/usr/bin/perl
use strict;
use warnings;
my $data = "111\n222\n\r333\r\n444\r555";
my %IRS = (
ord("\n") => '\n',
ord("\r") => '\r',
);
sub get_chr_list {
my ($irs) = @_;
return join( "", map( $IRS{ ord($_) }, split( //, $irs ) ) );
}
sub load_file {
my ( $filename, $irs ) = @_;
$irs = defined($irs) ? $irs : "";
printf( "Current INPUT_RECORD_SEPARATOR = %s\n", get_chr_list($irs) );
do {
local $/ = $irs;
open( FH, "$filename" );
while (<FH>) {
chomp;
$_ =~ s/\n/\\n/g;
$_ =~ s/\r/\\r/g;
print "[$_]\n";
}
close(FH);
}
}
sub main {
open( FH, ">/tmp/test.txt" );
print FH $data;
close(FH);
printf( "Default INPUT_RECORD_SEPARATOR = %s\n", get_chr_list($/) );
load_file( "/tmp/test.txt", "\n" );
load_file( "/tmp/test.txt", "\n\r" );
load_file( "/tmp/test.txt", "\r\n" );
load_file( "/tmp/test.txt", undef ); # slurp
}
main;
※ 引述《abliou (把青春freeze)》之铭言:
: ※ 引述《StarTouching (抚星)》之铭言:
: : 找到原因了....
: : 首先要先知道
: : Windows的 command-line(亦即DOS) 按Enter时会送出\r\n
: : 但是在txt中, 只有\n (也许整个非Dos环境都是如此)
: : chomp预设只会筛掉\n,
: : 所以如果从STDIN读入(DOS输入),
: : 就会仍遗留下\r
: : 改$/ = "\r\n"
: : 可让chomp筛掉\r\n
: : 但$/也影响到Perl读取字串的断点
: : 所以txt档里面只有\n 没有\r,
: : 那Perl就找不到断点,
: : 应该要把$/改回"\n"
: : 结论: 在Windows 需要DOS输入时, 才需要改 $/
: : 不过这状况其实不常用在实际应用,
: : 多半在练习或debug才会用,
: : 但正是因为如此, 初学者才更容易遇到这个问题而不知解决方法
: 看到这边就想到大约两年前的讨论串 不过往上爬文已经找不到了
: 有一种方法叫做slurp 作法就是把$/设为undef
: 这样在读档就会略过换行符号 把整个档的内容放到字串中
: 这种方法用在网页的tag处理很有用
: 因为在撷取网页资料时都是在撷取两个tag中间的资讯
: 所以无形中换行符号就变成一种问题
: (当然在常规表示式中会有解决方案)
: Perl中很多预设变数 在更改都会有用处跟用意 不过也要注意後面的影响
: ps.我承认我蛮菜的 不过目前我用过的perl 都还没碰过原po碰到的问题
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 140.114.64.130
1F:推 abliou:推阿 03/21 21:34