2014-07-22 62 views
0

您好可以有人請解釋一下我爲什麼有不同的輸出從以下兩個腳本的最後一行丟失:Perl的 - 打開文件 - 如果換行沒有最後一行後提出的

01.pl

#!/usr/bin/perl 
use warnings; 
use strict; 
use Data::Dumper; 

open FDGROUP, "< file" or die "Can't open file: $!\n"; 
my @file = <FDGROUP>; 
close FDGROUP; 

@file = grep {/\S/} @file; 

@file = grep {s/\r//} @file; 
@file = grep {s/\n//} @file; 

print Dumper @file; 

02.pl

#!/usr/bin/perl 
use warnings; 
use strict; 
use Data::Dumper; 

open FDGROUP, "< file" or die "Can't open file: $!\n"; 
my @file = <FDGROUP>; 
close FDGROUP; 

@file = grep {/\S/} @file; 

my $j = 0; 
foreach (@file){ 
    $_ =~ s/\r//; 
    $_ =~ s/\n//; 
    $file[$j++] = $_; 
} 

print Dumper @file; 

輸出:

[email protected] ~/scripts/stackoverflow 
$ perl 01.pl 
$VAR1 = '1'; 
$VAR2 = '2'; 
$VAR3 = '3'; 
$VAR4 = '4'; 
$VAR5 = '5'; 
$VAR6 = '6'; 

[email protected] ~/scripts/stackoverflow 
$ perl 02.pl 
$VAR1 = '1'; 
$VAR2 = '2'; 
$VAR3 = '3'; 
$VAR4 = '4'; 
$VAR5 = '5'; 
$VAR6 = '6'; 
$VAR7 = '7'; 

[email protected] ~/scripts/stackoverflow 
$ od -ab file 
0000000 1 cr nl 2 cr nl 3 cr nl 4 cr nl 5 cr nl 6 
     061 015 012 062 015 012 063 015 012 064 015 012 065 015 012 066 
0000020 cr nl 7 
     015 012 067 
0000023 

[email protected] ~/scripts/stackoverflow 
$ perl -e 'print $/' | od -ab 
0000000 nl 
     012 
0000001 

當我在我打開腳本文件的最後一行之後再添新行給出了相同的結果(7個變量)。我知道chomp用於這樣的操作,但是當我用下面的腳本:

#!/usr/bin/perl 
use warnings; 
use strict; 
use Data::Dumper; 

open FDGROUP, "< file" or die "Can't open file: $!\n"; 
my @file = <FDGROUP>; 
close FDGROUP; 

@file = grep {/\S/} @file; 
chomp @file; 
print Dumper @file; 

我獲得以下的輸出:

[email protected] ~/scripts/stackoverflow 
$ perl 03.pl 
';AR1 = '1 
';AR2 = '2 
';AR3 = '3 
';AR4 = '4 
';AR5 = '5 
';AR6 = '6 
';AR7 = '7 

這大概是CR空白或與它的東西引起的。

所有這些都在cygwin下完成。

謝謝

+1

'$ file [$ j ++] = $ _;'是不必要的:http://perldoc.perl.org/perlsyn。html#Foreach-Loops – toolic

+1

謝謝,值得了解它。 –

回答

2

有了這些語句:

@file = grep {/\S/} @file; # strips any element which doesn't have non-whitespace characters 
@file = grep {s/\r//} @file; # strips any elem which doesn't have a \r, strips \r from those that do 
@file = grep {s/\n//} @file; # strips any elem which doesn't have a \n, strips \n from those that do 

每次你建立一個新的數組。該新數組由與grep匹配的給定{ block }的輸入的所有元素組成。

由於最後一行遺漏了它的\n,它將忽略該行。

+0

哦,我看不到樹林。感謝澄清。是否有可能使用更優雅(grep或其他)的方式編寫它? –

+0

試過但沒有給出預期的結果:@file = grep {s/\ s $ // || $ _} @file; –

+0

假設你想過濾出空行並去掉CR/LF,'@file = grep {s/^(。*?)\ r?\ n?$/$ 1/&& length} @ file'將適用於Windows和Linux。有(很多)其他方法來實現同樣的事情。 – Leeft

1

只有匹配表達式時,grep纔有效。最後一行沒有\ n,所以它不會返回任何東西。

+0

謝謝你解釋 –

1

不像我的其他答案https://stackoverflow.com/a/24890193/3755747在技術上不是你真正想問什麼的答案......但你的代碼是一個老式的Perl,所以這裏有一些更現代的替代品。

完全寫出來的,基本的Perl:

use strict; 
use warnings; 
use Data::Printer; # I prefer this over Data::Dumper 

open(my $fh, '<', 'file') or die "can't open 'file': $!"; 

my @lines; 
while (my $line = <$fh>) { 
    $line =~ s/^(.*?)\r?\n?$/$1/; 
    next if $line eq ''; 
    push @lines, $line; 
} 
close $fh or die "can't close 'file': $!"; 

p(@lines); 

一個非常緊湊的版本,但解釋:

use strict; 
use warnings; 
use Data::Printer; 

my @lines = grep { 
    s/ 
     ^  # start of string 
      (.*?) # capture non-greedy match, without the ? it consumes the \r and \n as well 
      \r? \n? # optional CR, optional LF 
     $   # end of string 
    /$1/x  # replace with the match, whitespace allowed in regex 
    && length  # and string has to have some length remaining 
} read_file('file'); 

p(@lines); 

不同的方式,使用split

use Modern::Perl '2012'; 
use File::Slurp; 
use Data::Printer; 

# added parenthesis around split arguments for clarity, they're not needed 
my @lines = grep { length } split(/\r?\n/, read_file 'file'); 
p(@lines); 

咕嘟咕嘟地是完全可能沒有模塊:

use Modern::Perl; 
use Data::Printer; 

open(my $fh, '<', 'file') or die "can't open 'file': $!"; 
my @lines = grep { s/^(.*?)\r?\n?$/$1/ && length } <$fh>; 
close $fh or die "can't close 'file': $!"; 

p(@lines); 

我想我更喜歡split版本。

+0

感謝您的提示 –