
Tengo un enorme archivo de copia de seguridad de MySQL (de mysqldump) con las tablas en orden alfabético. Mi restauración falló y quiero continuar donde lo dejé con la siguiente tabla en el archivo de respaldo. (He corregido el problema, en realidad no se trata de restauraciones de MySQL, etc.)
Lo que me gustaría hacer es tomar mi archivo de respaldo, por ejemplo, backup.sql
y recortar el comienzo del archivo hasta que vea esta línea:
-- Table structure for `mytable`
Luego, todo lo que siga terminará en mi archivo de resultados, por ejemplo backup-secondhalf.sql
. Esto es algo complicado por el hecho de que el archivo está comprimido con bzip2, pero eso no debería ser gran cosa.
Creo que puedo hacerlo así:
$ bunzip2 -c backup.sql.bz2 | grep --text --byte-offset --only-matching -e '--Table structure for table `mytable`' -m 1
Esto me dará el desplazamiento de bytes en el archivo que quiero recortar.hasta. Entonces:
$ bunzip2 -c backup.sql.bz2 | dd skip=[number from above] | bzip2 -c > backup-secondhalf.sql.bz2
Desafortunadamente, esto requiere que ejecute bunzip2 en el archivo dos veces y lea todos esos bytes dos veces.
¿Hay alguna manera de hacer esto todo a la vez?
No estoy seguro de que mi sed-fu sea lo suficientemente fuerte como para hacer una expresión de "eliminar todas las líneas hasta la expresión regular y luego dejar pasar el resto del archivo".
Esto está en Debian Linux, por lo que tengo herramientas GNU disponibles.
Respuesta1
bunzip2 -c backup.sql.bz2 | \
sed -n '/-- Table structure for `mytable`/,$p'
Explicación:
-n suppress automatic printing of pattern space
Construcción del rango de direcciones: comience con expresiones regulares
/-- Table structure for `mytable`/
Terminar con
$ Match the last line.
Dominio
p Print the current pattern space.
Editar: dependiendo de cómo descartó la base de datos, es posible que tengamuylíneas largas. GNU sed puede manejarlos hasta la cantidad de memoria disponible.
Respuesta2
NOTA: No es una respuesta real
Ya que estaba motivado para resolver esto.ahora, Seguí adelante y solía grep
encontrar el desplazamiento en el archivo que quería; funcionó muy bien.
Desafortunadamente, ejecutarlo dd
requiere que lo configures, ibs=1
lo que básicamente significa que no hay almacenamiento en búfer y el rendimiento es terrible. Mientras esperaba que se completara dd, dediqué tiempo a escribir mi propio programa C personalizado para omitir los bytes. Después de haber hecho eso, veo que tail
podría haberlo hecho por mí con la misma facilidad:
$ bunzip2 -c restore.sql.bz2 | tail -c +[offset] | bzip2 -c > restore-trimmed.sql.bz2
Digo "esto no responde a mi pregunta" porque todavía requiere dos pasadas por el archivo: una para encontrar el desplazamiento de lo que estoy buscando y otra para recortar el archivo.
Si volviera a mi programa personalizado, podría implementar unKMPdurante la fase de "solo lectura" del programa y luego cambie a "leer+escribir todo" después de eso.
Respuesta3
Me pregunto si algo así funcionaría:
use strict;
use warnings;
use feature 'say';
use IO::Uncompress::Bunzip2 '$Bunzip2Error';
my $file = $ARGV[0] // die "need a file";
my $zh = IO::Uncompress::Bunzip2->new( $file, {
AutoClose => 1,
Transparent => 1,
} ) or die "IO::Uncompress::Bunzip2 failed: $Bunzip2Error\n";
my $trigger = undef;
while ( <$zh> ) {
chomp;
$trigger = 1 if $_ eq '-- Dumping data for table `experiments`';
say if $trigger;
}
Básicamente, comienza a imprimir cosas después del patrón, también se puede canalizar directamente a bzip2/gzip, como perl chop.pl input_sql.bz2 | bzip2 > out.sql.bz2
lo necesitarías libio-compress-perl
en Debian.