Bylo zde několik otázek týkajících se nahrazení víceřádkových řetězců pomocí unixového shellu, ale nenašel jsem žádný, který by v této situaci fungoval.
Snažím se odstranit klíče a omezení z některých MySQL DDL, které vypadají takto (jeden příklad):
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;
Chci odstranit vše od čárky končící řádek před 'PRIMARY KEY' až po, ale ne včetně ') ENGINE=' (mezi nimi může být nula nebo více řádků a nebudou vždy začínat KEY nebo mít závorky, ale ') ENGINE=' je konzistentní). Výsledek by měl vypadat takto:
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;
Jsem otevřený použití jakéhokoli standardního nástroje příkazového řádku (např. sed, perl, awk), ale protože tyto soubory mohou být poměrně velké (některé jsou v řádu desítek nebo stovek GB), musí být efektivní. Vzhledem k tomu, že soubory jsou obvykle uloženy ve formátu gzip (nebo někdy zpracuji výstup nástroje mysql dump přímo, místo toho, abych nejprve zapisoval na disk), potřebuji něco, co lze pomocí pipetování a zpět.
Přijatá odpověď:
Ponechte stav, zda chcete vytisknout předchozí řádek, v případě potřeby čárku odstraňte. Tato metoda uchovává v paměti pouze jeden nebo dva řádky souboru.
#!/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;