11
votes

Comment extraire des lignes entre deux délimiteurs de ligne dans Perl?

J'ai un fichier journal ASCII avec du contenu que j'aimerais extraire. Je n'ai jamais pris le temps d'apprendre Perl correctement, mais je pense que c'est un bon outil pour cette tâche.

Le fichier est structuré comme celui-ci: p>

... 
... 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


4 commentaires

Utilisez le match global / g plutôt que de le laisser arrêter au terminal de ligne.


Vous vouliez dire / s? Afaik / g est Match multiple .


Ceci est une question en double. Voir .... stackoverflow.com/questions/296366/...


Voir aussi Comment Lignes d'impression entre deux modèles, inclus ou exclusive


6 Réponses :


1
votes

Comment puis-je saisir plusieurs lignes après une ligne correspondante à Perl?

Comment est-ce celui-là? Dans celui-ci, la chaîne d'extrémité est $ ^, vous pouvez le changer à votre chaîne de fin.

Je suis aussi novice, mais les solutions offrent de nombreuses méthodes ... laissez-moi savoir plus spécifiquement ce que vous voulez que cela diffère du lien ci-dessus.


0 commentaires

23
votes

Vous voulez que l'opérateur de flip-flop (également appelé l'opérateur de plage) .. xxx

remplace l'appel à Imprimer Avec tout ce que vous voulez réellement faire (par exemple, appuyez sur la ligne dans un tableau, éditer-le, formatez-le, peu importe). Je suis Suivant -ing -ing passé les lignes qui ont réellement Démarrer ou fin , mais vous ne voulez peut-être pas que ce comportement. Voir Cet article pour une discussion de cet opérateur et Autres variables spéciales perl utiles.


5 commentaires

Travaille pour moi!! Étant donné que je veux exclure les lignes avec les délimiteurs, je peux pipeler la sortie via Grep -V par exemple. BTW, en première ligne après le début, comment pourrais-je supprimer le premier personnage d'une ligne?


La version one-liner: Perl -ne 'Imprimer si / /start/../end/'


William, qui imprimera les lignes avec début et fin. Si vous ne le souhaitez pas, voici l'ONLINAINE DE TELEMACHUS: PERL -NE 'IF (/START/../end/) {IMPRIMER SAUF / START / OR / FIN /}' '


@Telemachus - Comment puis-je obtenir ceci pour travailler avec une variable plutôt que de lire un fichier. Dis que j'ai un $ variable = "Ne voulez pas que cette partie commence, je veux cette partie à la place finale"; ? Parce que j'ai du mal à obtenir le même effet lorsqu'il s'agit d'une variable par opposition à un fichier, votre aide est très appréciée, merci


@ Perl-utilisateur si la chaîne est plus longue (et surtout si elle est séparée par des lignes neuves ou quelque chose de très régulier), vous pouvez utiliser ouvrir et traiter une variable de chaîne comme un fichier de fichiers. Mais si la corde ressemble vraiment à ce que vous avez ici, cela ne semble pas la peine. Vous pouvez simplement utiliser la substitution pour supprimer les pièces que vous ne voulez pas: s /^.* start // puis s / fin $ // , par exemple. Si c'est plus complexe, j'ouvre une nouvelle question.



1
votes
while (<>) {
    chomp;      # strip record separator
    if(/END/) { $f=0;}
    if (/START/) {
        s/.*START//g;
        $f=1;
    }
    print $_ ."\n" if $f;
}
try to write some code next time round

1 commentaires

Je comprends et j'aurais écrit du code si j'avais déjà commencé à apprendre Perl. J'ai réussi à passer avec Awk et Sed jusqu'à présent. Mais de toute façon, merci pour votre conseil.



1
votes

Après la réponse de Telemachus, les choses ont commencé à verser. Cela fonctionne comme la solution que je regarde après tout.

  1. J'essaie d'extraire des lignes délimitées par deux cordes (une, avec une ligne se terminant par "Cinfile ="; autre, avec une ligne contenant une seule "#") dans des lignes distinctes, à l'exclusion des lignes de délimitation. Ceci que je peux faire avec la solution de Telemachus.
  2. La première ligne a un espace que je veux supprimer. Je comprends aussi ça.
  3. J'essaie également d'extraire chaque ligne définie dans des fichiers distincts.

    Cela fonctionne pour moi, bien que le code puisse être classé comme laid; C'est parce que je suis actuellement un nouveau venu à Perl. Quoi qu'il en soit, voici: xxx

    J'espère que cela profite également aux autres. Bravo.


0 commentaires

5
votes

de Réponse de Perlfaq6 à Comment puis-je extraire des lignes entre deux motifs qui sont eux-mêmes sur différentes lignes?


Vous pouvez utiliser un opérateur quelque peu exotique de Perl. (documenté dans Perlop): p> xxx pré>

Si vous vouliez du texte et non des lignes, vous utiliseriez P>

while (<>) {
    $in_header =   1  .. /^$/;
    $in_body   = /^$/ .. eof;
# now choose between them
} continue {
    $. = 0 if eof;  # fix $.
}


0 commentaires

1
votes

Pas trop mal pour venir d'un "nouveau-livrer virtuel". Une chose que vous pourriez faire est de mettre le "$ trouvée = 1" à l'intérieur du "if ($ trouvés == 0)" de sorte que vous ne faites pas cette affectation à chaque fois entre $ départ et $ STOP.

Une autre chose qui est un peu laide, à mon avis, est que vous ouvrez le même fichierHandler chaque fois que vous entrez dans le bloc $ start / $ $. P>

Ceci montre un moyen de contourner cela: P >

#!/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                                                           

}


2 commentaires

Merci. Je pense maintenant que je devrais perdre du temps pour apprendre correctement Perl. Mon arrière-plan est sur C, certains C ++ et certains Fortran, de sorte qu'il semble familier.


BTW, j'avoue que j'étais laxiste sur l'ouverture de nombreux dossiers, ma principale préoccupation à l'époque consistait à obtenir quelque chose qui fonctionnait, même pas trop bien.