最简洁的Perl解析器,用于类似Makefile的延续线

Tom*_*ime 3 perl redo fileparsing

我正在编写的perl脚本需要解析一个包含Makefile等延续行的文件.即以空格开头的行是前一行的一部分.

我写下面的代码,但不觉得它很干净或perl-ish(哎呀,它甚至不使用"重做"!)

有许多边缘情况:奇数位置的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;
Run Code Online (Sandbox Code Playgroud)

Nic*_*son 6

如何将整个文件压入内存并使用正则表达式处理它.更多'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;
Run Code Online (Sandbox Code Playgroud)