Frage

Ich habe eine ASCII-Protokolldatei mit einigen Inhalten würde ich extrahieren möchte. Ich habe nie die Zeit genommen Perl richtig zu lernen, aber ich glaube dies ein gutes Werkzeug für diese Aufgabe ist.

Die Datei wird wie folgt strukturiert:

... 
... some garbage 
... 
... garbage START
what i want is 
on different
lines 
END 
... 
... more garbage ...
next one START 
more stuff I want, again
spread 
through 
multiple lines 
END 
...
more garbage

Also, ich bin auf der Suche nach einer Möglichkeit, die Linien zwischen den einzelnen START und END Begrenzer Strings zu extrahieren. Wie kann ich das tun?

Bisher hat ich finde nur einige Beispiele dafür, wie eine Zeile mit dem START String oder anderer Dokumentation Artikeln zu drucken, die etwas im Zusammenhang mit dem, was ich suche.

War es hilfreich?

Lösung

Sie möchten die Flip-Flop-Operator (besser als der Bereich Operator bekannt) ..

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

while (<>) {
  if (/START/../END/) {
    next if /START/ || /END/;
    print;
  }
}

Ersetzen Sie den Aufruf mit print, was Sie wirklich wollen, tun (zum Beispiel, drücken Sie die Zeile in einem Array, bearbeiten, formatieren Sie ihn, was auch immer). Ich bin next-ing vorbei an den Linien, die tatsächlich START oder END haben, aber Sie können nicht dieses Verhalten möchten. Siehe diesem Artikel für eine Diskussion dieses Operators und andere nützliche Perl spezielle Variablen.

Andere Tipps

perlfaq6 's Antwort auf

Wie kann ich packen mehr Linien nach einer passenden Zeile in Perl?

Wie ist das ein? In diesem einen ist die END string $ ^, können Sie es zu Ihrem END Zeichenfolge ändern können.

Ich bin auch ein Neuling, aber die Lösungen dort schon einige Methoden bieten ... lassen Sie mich wissen, genauer gesagt, was Sie wollen, dass aus den obigen Link abweicht.

while (<>) {
    chomp;      # strip record separator
    if(/END/) { $f=0;}
    if (/START/) {
        s/.*START//g;
        $f=1;
    }
    print $_ ."\n" if $f;
}

versuchen einige Code beim nächsten Mal schreiben

Nach dem Telemachos Antwort, begann Dinge Ausgießen. Dies funktioniert wie die Lösung auf, nachdem alles, was ich bin auf der Suche.

  1. Ich versuche Linien von zwei Strings begrenzt zu extrahieren (eines, mit einer Linie mit der Endung „CINFILE =“; andere, mit einer Linie eines einzigen „#“ enthält) in getrennten Linien, mit Ausnahme der Begrenzungslinien. Das kann ich Lösung mit Telemachos tun.
  2. Die erste Zeile hat einen Raum, den ich entfernen möchten. Ich schließe es auch.
  3. Ich versuche auch jede Zeile-Set in separate Dateien zu extrahieren.

Dies funktioniert für mich, obwohl der Code kann als hässlich eingestuft werden; dies liegt daran, dass ich zur Zeit ein praktisch Neuling in Perl bin. Auf jeden Fall hier geht:

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

my $start='CINFILE=$';
my $stop='^#$';
my $filename;
my $output;
my $counter=1;
my $found=0;

while (<>) {
  if (/$start/../$stop/) {
    $filename=sprintf("boletim_%06d.log",$counter);
    open($output,'>>'.$filename) or die $!;
    next if /$start/ || /$stop/;
    if($found == 0) { print $output (split(/ /))[1]; }
    else { print $output $_; }
    $found=1;
  } else { if($found == 1) { close($output); $counter++; $found=0; } }
}

Ich hoffe, dass es auch andere Vorteile. Prost.

Nicht schlecht für von einem „virtuellen Newcommer“ kommen. Eine Sache, die Sie tun können, ist, die setzen „gefunden $ = 1“ innerhalb des „if ($ gefunden == 0)“ Block, so dass Sie nicht, dass die Zuordnung tun, jedes Mal zwischen $ beginnen und $ stoppen.

Ein andere Sache, die ein bisschen hässlich, meiner Meinung nach ist, ist, dass Sie die gleichen Filehandler jedes Mal, wenn der $ Start / $ Stop-Blockes eingeben öffnen.

Dies zeigt eine Art und Weise um, dass:

#!/usr/bin/perl

use strict;
use warnings;

my $start='CINFILE=$';
my $stop='^#$';
my $filename;
my $output;
my $counter=1;
my $found=0;

while (<>) {

    # Find block of lines to extract                                                           
    if( /$start/../$stop/ ) {

        # Start of block                                                                       
        if( /$start/ ) {
            $filename=sprintf("boletim_%06d.log",$counter);
            open($output,'>>'.$filename) or die $!;
        }
        # End of block                                                                         
        elsif ( /$end/ ) {
            close($output);
            $counter++;
            $found = 0;
        }
        # Middle of block                                                                      
        else{
            if($found == 0) {
                print $output (split(/ /))[1];
                $found=1;
            }
            else {
                print $output $_;
            }
        }

    }
    # Find block of lines to extract                                                           

}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top