2012-03-23 14 views
2

Ich muss mehrzeilige Datensätze einlesen und auf genau 40 Zeilen zuschneiden. Dann packen Sie sie mit zu 45 Zeilen. Sie können so groß wie 70 + Zeilen sein. Diese Datensätze benötigen , um am Ende 45 Zeilen zu sein.Perl: Mehrzeilige Datensätze trimmen

Das Datensatztrennzeichen ist eine Zeile, die mit dem Muster/^ # matchee/beginnt.

Ich nehme an, Sie würden $/auf #matchee setzen.

{ 
    $/ = "#matchee"; 

    while (<>) { 
     # I need to print first 40 
     # lines of each record then 
     # pad to 45 with delimiter as 
     # last line. 
    } 
} 

Beispielprotokoll

REDUNDANCY DEPARTMENT 
Anonymous Ave 

Item 1 
Item 2 



<bunch of blank lines> 
#matchee 

Antwort

1

Hier ist meine Lösung ...

#! /usr/bin/env perl 
use strict; 
use warnings; 

{ 
    $/ = "#matchee"; 

    while (my @line = split "\n", <>) { 

    # print first 40 lines of record 
     for my $counter (0..39) { 
      print($line[$counter] . "\n"); 
     } 

     # pad record with four extra blank lines 
     # (last record already ends with a newline) 
     print "\n" x 4; 
    } 
} 

+1 für die Verwendung von $/ = "#matchee";

Das ist nicht ganz richtig ... der erste Datensatz hat 45 Zeilen, die zweite hat 44.

+1

'für meine $ counter (0..39) {...}' – vol7ron

+0

Guter Vorschlag. Bearbeiteter Code entsprechend. –

+0

Wenn Sie eine neuere Version von Perl verwenden, können Sie 'say '..."; 'anstelle von' print' ... \ n ";' ausführen, obwohl ich mir nicht ganz sicher bin, ob Sie die Leitungsbeendigungsvariable setzen . Auch sollte es '#!/Usr/bin/...' sein (kein Leerzeichen) – vol7ron

1

Sie geben an, dass "das Datensatztrennzeichen eine Zeile ist, die mit dem Muster/^ # matchee /" beginnt. Dies erschwert die Aufzeichnungstrennung etwas, da $/a special string, but not a regex ist. Sie haben nicht angegeben, ob Ihre Ausgabe dasselbe Datensatztrennzeichen verwendet, aber ich nehme an. Hier ist ein Ansatz, der zu funktionieren scheint.

#!/usr/bin/env perl 
use strict; 
use warnings; 

sub take_and_pad_lines { 
    my ($str, $take, $pad) = @_; 

    my @lines = (split(/\n/, $str))[0..$take-1]; 
    return join "\n", @lines, ('') x ($pad - $take); 
} 


{ 
    $/ = "#matchee"; 

    while (my $record = <>) { 
    # because RS is really begins-with we must clean up first line 
    # and double check last record 
    unless (1 == $.) { 
     $record =~ s/\A.*\n//m; 
     last if eof() && $record eq ''; 
    } 

    print take_and_pad_lines($record, 40, 45), "\n"; 
    print "$/\n" unless eof(); 
    } 
} 
+0

Aha. Das erklärt, warum ich eine unterschiedliche Anzahl von Zeilenvorschüben erhielt, die im ersten und zweiten Datensatz enthalten waren ... der erste Datensatz begann nicht mit dem Begrenzer und war daher eine Zeile kürzer als der Rest. –

+0

Ich gebe das eine Chance. Vielen Dank! – Bubnoff

+0

@Bubnoff hat das für dich geklappt? – dbenhur