GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Mehrzeilige Sed ersetzen

AWK-Antwort

Mit Ihrem Beispieltext in einer Datei namens sql , das folgende Muster (mit Zeilenumbrüchen und Einrückungen zur Verdeutlichung):

awk -v skip=1 '{
    if (skip) { skip=0 }
    else {
        if (/FULLTEXT KEY/) { skip=1; sub(/,$/, "", prevline) }
        print prevline
    }
    prevline=$0
}
END { print prevline }' sql

produziert:

CREATE TABLE `table` (
  `id` int(10) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL default '',
  `description` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

Erklärung:

  • Wir implementieren "Lookahead", indem wir nur vorher drucken angetroffene Zeile bei jeder Iteration, nachdem die aktuelle Zeile überprüft wurde.
  • Falls die aktuelle Zeile den FULLTEXT KEY enthält marker setzen wir ein Flag, um das Drucken dieser Zeile während der nächsten Iteration zu überspringen. Wir entfernen auch das abschließende Komma in der vorherigen Zeile, die gedruckt werden soll.
  • Wir überspringen das Drucken einer leeren Anfangszeile (vor prevline eingestellt wurde) durch anfängliches Setzen von skip bis 1 ("wahr").
  • Wir stellen sicher, dass die letzte Zeile gedruckt wird, indem wir das Skript mit einem zusätzlichen prevline beenden drucken. Beachten Sie, dass die aktuelle Implementierung davon ausgeht, dass diese letzte Zeile keine Zeile ist, die übersprungen werden könnte, d. h. dass sie nicht den FULLTEXT KEY enthält Markierung.

Original (unvollständig) sed Antwort

Diese Antwort ist unvollständig und sicherlich in den meisten Fällen falsch, seit sed verbraucht den Eingabestrom zu schnell für das beabsichtigte Ergebnis, wenn mehrzeilige Übereinstimmungen durchgeführt werden - wie in den Kommentaren erwähnt, funktioniert dies nur für Übereinstimmungen in geradzahligen Zeilen! sed hat keine "echte" Lookahead-Funktionalität, also wären wir besser dran, Python/Perl/etc. oder tatsächlich AWK wie oben zu verwenden.

Mit Ihrem Beispieltext in einer Datei namens sql , das folgende Muster:

$ sed 'N; s/,\n  FULLTEXT.*//' sql

produziert:

CREATE TABLE `table` (
  `id` int(10) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL default '',
  `description` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;

Erklärung:

  • N aktiviert den mehrzeiligen Abgleich.
  • \n stellt einen Zeilenumbruch dar.
  • s/pattern/replacement/ ist die Standard-Ersetzungssyntax.
  • .* findet alles bis zum Ende der aktuellen Zeile.

Linux
  1. Verwenden von Sed zum Suchen und Ersetzen einer Linie zwischen Musterbereichen

  2. So ersetzen Sie eine Zeichenfolge in mehreren Dateien in der Linux-Befehlszeile

  3. Finden Sie passenden Text und ersetzen Sie die nächste Zeile

  4. ersetzt das n-te Vorkommen von String in jeder Zeile einer Textdatei

  5. sed:Wie wird eine Zeile ersetzt, wenn sie gefunden wird, oder an das Ende der Datei angehängt, wenn sie nicht gefunden wird?

Top 20 der zu verwendenden sed-Befehle

Unix Sed Tutorial:Dateizeilen anhängen, einfügen, ersetzen und zählen

Unix Sed Tutorial:Mehrzeilige Dateioperation mit 6 praktischen Beispielen

Konvertieren Sie die Zeichenfolge in der Befehlszeile in Hexadezimal

Ersetzen Sie Zeilen in einer Datei durch Zeilen in einer anderen durch die Zeilennummer

SED-Ersetzung über mehrere Zeilen hinweg