GNU/Linux >> Tutoriels Linux >  >> Linux

Supprimer les chaînes multilignes ?

Plusieurs questions ont été posées ici concernant le remplacement de chaînes multilignes à l'aide du shell Unix, mais je n'en ai trouvé aucune qui fonctionnerait dans cette situation.

J'essaie de supprimer les clés et les contraintes de certains DDL MySQL, qui ressemblent à ceci (un exemple) :

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;

Je veux tout supprimer de la virgule terminant la ligne avant 'PRIMARY KEY' jusqu'à, mais sans inclure ') ENGINE=' (il peut y avoir zéro ou plusieurs lignes entre celles-ci, et elles ne commenceront pas toujours par KEY ou n'auront pas le entre parenthèses, mais le ') ENGINE=' est cohérent). Le résultat devrait ressembler à ceci :

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;

Je suis ouvert à l'utilisation de n'importe quel utilitaire de ligne de commande standard (par exemple, sed, perl, awk), mais comme ces fichiers peuvent être assez volumineux (certains sont de l'ordre de dizaines ou de centaines de Go), ils doivent être efficaces. Étant donné que les fichiers sont généralement stockés compressés (ou parfois je traite directement la sortie de l'utilitaire de vidage mysql plutôt que d'écrire d'abord sur le disque), j'ai besoin de quelque chose qui peut être acheminé vers et depuis.

Réponse acceptée :

Gardez l'état sur l'impression ou non de la ligne précédente, modifiez-le pour supprimer la virgule si nécessaire. Cette méthode ne garde qu'une ou deux lignes du fichier en mémoire.

#!/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. Supprimer récursivement des fichiers en toute sécurité :déchiquetage

  2. Remappage de la touche d'alimentation à supprimer ?

  3. Comment concaténer des chaînes dans Bash

  4. Commande Linux rm

  5. Supprimer les mises à jour Windows téléchargées

Chaînes de concaténation bash

Comment comparer des chaînes dans Bash

Comment supprimer des lignes dans Vim / Vi

Comment utiliser bash if -z et if -n pour tester des chaînes sous Linux

/dev/null sous Linux

Installez PowerDNS sur Ubuntu 18.04, 20.04 et 22.04