메이크 파일과 같은 연속선을위한 가장 깨끗한 perl 파서
-
05-07-2019 - |
문제
내가 쓰고있는 Perl 스크립트는 makefile과 같은 연속선이있는 파일을 구문 분석해야합니다. 공백으로 시작하는 IE 라인은 이전 줄의 일부입니다.
나는 아래에 코드를 썼지 만 매우 깨끗하거나 perl-ish라고 느끼지 않습니다 (도대체, 그것은 "redo"를 사용하지 않습니다!)
홀수 장소, 단일 라인 파일, 빈 줄 (또는 비-송금 라인 또는 연속선)으로 시작하거나 끝나는 파일, 빈 파일의 EOF가 많이 있습니다. 내 모든 테스트 사례 (및 코드)는 다음과 같습니다. http://whatexit.org/tal/flatten.tar
내 모든 테스트를 통과하는 클리너, Perl-ish, 코드를 작성할 수 있습니까?
#!/usr/bin/perl -w
use strict;
sub process_file_with_continuations {
my $processref = shift @_;
my $nextline;
my $line = <ARGV>;
$line = '' unless defined $line;
chomp $line;
while (defined($nextline = <ARGV>)) {
chomp $nextline;
next if $nextline =~ /^\s*#/; # skip comments
$nextline =~ s/\s+$//g; # remove trailing whitespace
if (eof()) { # Handle EOF
$nextline =~ s/^\s+/ /;
if ($nextline =~ /^\s+/) { # indented line
&$processref($line . $nextline);
}
else {
&$processref($line);
&$processref($nextline) if $nextline ne '';
}
$line = '';
}
elsif ($nextline eq '') { # blank line
&$processref($line);
$line = '';
}
elsif ($nextline =~ /^\s+/) { # indented line
$nextline =~ s/^\s+/ /;
$line .= $nextline;
}
else { # non-indented line
&$processref($line) unless $line eq '';
$line = $nextline;
}
}
&$processref($line) unless $line eq '';
}
sub process_one_line {
my $line = shift @_;
print "$line\n";
}
process_file_with_continuations \&process_one_line;
해결책
전체 파일을 메모리로 비 슬러어하고 정규 표현식을 사용하여 처리하는 것은 어떻습니까? 훨씬 더 많은 'perlish'. 이것은 당신의 테스트를 통과합니다 많이 더 작고 깔끔한 :
#!/usr/bin/perl
use strict;
use warnings;
$/ = undef; # we want no input record separator.
my $file = <>; # slurp whole file
$file =~ s/^\n//; # Remove newline at start of file
$file =~ s/\s+\n/\n/g; # Remove trailing whitespace.
$file =~ s/\n\s*#[^\n]+//g; # Remove comments.
$file =~ s/\n\s+/ /g; # Merge continuations
# Done
print $file;
다른 팁
메모리에서 전체 파일을로드하는 것이 마음에 들지 않으면 아래 코드가 테스트를 통과합니다. 라인을 배열에 저장하여 각 라인을 이전 라인 (연속) 또는 배열 끝에 (기타)에 추가합니다.
#!/usr/bin/perl
use strict;
use warnings;
my @out;
while( <>)
{ chomp;
s{#.*}{}; # suppress comments
next unless( m{\S}); # skip blank lines
if( s{^\s+}{ }) # does the line start with spaces?
{ $out[-1] .= $_; } # yes, continuation, add to last line
else
{ push @out, $_; } # no, add as new line
}
$, = "\n"; # set output field separator
$\ = "\n"; # set output record separator
print @out;
제휴하지 않습니다 StackOverflow