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

Mehrzeilige Zeichenfolgen löschen?

Hier gab es mehrere Fragen zum Ersetzen mehrzeiliger Zeichenfolgen mithilfe der Unix-Shell, aber ich habe keine gefunden, die in dieser Situation funktioniert.

Ich versuche, Schlüssel und Einschränkungen aus einigen MySQL-DDLs zu entfernen, die wie folgt aussehen (ein Beispiel):

CREATE TABLE `access_group` (
  `GROUP_ID` int(10) NOT NULL AUTO_INCREMENT,
  `PARENT_GROUP_ID` int(10) DEFAULT NULL,
  `GROUP_NAME` varchar(45) NOT NULL,
  `GROUP_DESC` varchar(45) NOT NULL DEFAULT '',
  PRIMARY KEY (`GROUP_ID`),
  KEY `testkey` (`PARENT_GROUP_ID`)
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=latin1;

Ich möchte alles vom Komma entfernen, das die Zeile vor 'PRIMARY KEY' bis einschließlich ') ENGINE=' beendet (es können null oder mehrere Zeilen zwischen diesen sein, und sie beginnen nicht immer mit KEY oder haben die Klammern, aber das ') ENGINE=' ist konsistent). Das Ergebnis sollte so aussehen:

CREATE TABLE `access_group` (
  `GROUP_ID` int(10) NOT NULL AUTO_INCREMENT,
  `PARENT_GROUP_ID` int(10) DEFAULT NULL,
  `GROUP_NAME` varchar(45) NOT NULL,
  `GROUP_DESC` varchar(45) NOT NULL DEFAULT ''
) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=latin1;

Ich bin offen für die Verwendung jedes Standard-Befehlszeilenprogramms (z. B. sed, perl, awk), aber da diese Dateien ziemlich groß sein können (einige sind in der Größenordnung von zehn oder hundert GB), müssen sie effizient sein. Da die Dateien normalerweise gzippt gespeichert werden (oder ich manchmal die Ausgabe des mysql-Dump-Dienstprogramms direkt verarbeite, anstatt sie zuerst auf die Festplatte zu schreiben), brauche ich etwas, in das und aus dem es geleitet werden kann.

Akzeptierte Antwort:

Geben Sie an, ob die vorherige Zeile gedruckt werden soll, und bearbeiten Sie den Befehl, um das Komma bei Bedarf zu entfernen. Diese Methode behält nur eine oder zwei Zeilen der Datei im Speicher.

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

my $printing = 1;
my $previous;

# reads from standard input (optionally with the conventional -) or from
# the named files
shift @ARGV if @ARGV == 1 and $ARGV[0] eq '-';
while ( my $line = readline ) {
    if ( $line =~ m/^\s+PRIMARY KEY/ ) {
        $previous =~ s/,[ \t]*$//;
        $printing = 0;
    } elsif ( $line =~ m/^\) ENGINE/ ) {
        $printing = 1;
    } elsif ( !$printing ) {
        undef $previous;
    }
    print $previous if defined $previous;
    $previous = $line if $printing;
}
# don't forget last line after fall off the end of input (eof)
print $previous if defined $previous;

Linux
  1. Rm-Option zum Scheitern bei nicht vorhandenen Dateien?

  2. Automatisierung der Eingabe von Zeichenfolgen in Xmacro?

  3. So löschen Sie einen Dienst in Kubernetes

  4. So verketten Sie Strings in Bash

  5. Heruntergeladene Windows-Updates löschen

Bash Strings verketten

So vergleichen Sie Zeichenfolgen in Bash

So löschen Sie Zeilen in Vim / Vi

So verwenden Sie bash if -z und if -n zum Testen von Zeichenfolgen in Linux

/dev/null unter Linux

Installieren Sie PowerDNS auf Ubuntu 18.04, 20.04 und 22.04