4 Stimmen

Wie man 4 aufeinander folgende leere Zeilen in einer einzigen Zeile in Perl komprimiert.

Ich schreibe gerade ein Perl-Skript, um ein Protokoll zu lesen, um die Datei in ein neues Protokoll umzuschreiben, indem leere Zeilen entfernt werden, falls vier oder mehr aufeinander folgende leere Zeilen vorkommen. Mit anderen Worten, ich muss vier aufeinander folgende leere Zeilen (oder mehr Zeilen) in eine einzige Zeile komprimieren; aber jeder Fall von 1, 2 oder 3 Zeilen in der Datei muss im Format bleiben. Ich habe versucht, die Lösung online zu finden, aber das Einzige, was ich finden kann, ist

perl -00 -pe ''

oder

perl -00pe0  

Außerdem sehe ich das Beispiel in vim so, dass Blöcke von 4 leeren Zeilen gelöscht werden :%s/^\n\{4}//, was dem entspricht, wonach ich suche, aber es war in vim und nicht in Perl. Kann mir jemand dabei helfen? Danke.

8voto

Zaid Punkte 35800

Um 4 oder mehr aufeinanderfolgende Unix-Style-Zeilenumbrüche in eine einzelne neue Zeile zu kollabieren:

$ perl -0777 -pi.bak -e 's|\n{4,}|\n|g' file.txt

Ein alternativer Ansatz unter Verwendung von Lookbehind:

$ perl -0777 -pi.bak -e 's|(?<=\n)\n{3,}||g' file.txt

1voto

perreal Punkte 89574
verwenden Sie streng;
verwenden Sie Warnungen;

my $cnt = 0;

sub flush_ws {
  $cnt = 1 if ($cnt >= 4);
  while ($cnt > 0) {print "\n"; $cnt--; }
}

während (<>) {
  if (/^$/) {
    $cnt++;
  } else {
    flush_ws();
    print $_;
  }
}
flush_ws();

0voto

memowe Punkte 2636

Ihr -0 Hinweis ist gut, da Sie -0777 verwenden können, um die gesamte Datei im -p-Modus einzulesen. Lesen Sie mehr über diese Typen in perlrun. Daher sollte dieser Oneliner den Trick machen:

$ perl -0777 -pe 's/\n{5,}/\n\n/g'

Wenn bis zu vier neue Zeilen hintereinander vorhanden sind, passiert nichts. Fünf oder mehr neue Zeilen (vier oder mehr leere Zeilen) werden durch zwei neue Zeilen (eine leere Zeile) ersetzt. Beachten Sie hier den /g-Schalter, um nicht nur das erste Vorkommen zu ersetzen.

Deparsieter Code:

BEGIN { $/ = undef; $\ = undef; }
LINE: while (defined($_ = )) {
    s/\n{5,}/\n\n/g;
}
continue {
    die "-p-Ziel: $!\n" unless print $_;
}

HTH! :)

0voto

Steve Punkte 45842

Auf eine Weise mit GNU awk, indem der Datensatztrenner auf NUL gesetzt wird:

awk 'BEGIN { RS="\0" } { gsub(/\n{5,}/,"\n")}1' file.txt

Dies setzt voraus, dass deine Definition von leer Leerzeichen ausschließt

0voto

Borodin Punkte 124906

Dies wird tun, was du brauchst

perl -ne 'if (/\S/) {$n = 1 if $n >= 4; print "\n" x $n, $_; $n = 0} else {$n++}' myfile

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X