대용량 파일의 시작 부분에서 텍스트를 제거하는 가장 좋은 방법

대용량 파일의 시작 부분에서 텍스트를 제거하는 가장 좋은 방법

나는 테이블이 알파벳 순서로 포함된 거대한 MySQL 백업 파일(mysqldump의)을 가지고 있습니다. 복원에 실패했으며 백업 파일의 다음 테이블을 사용하여 중단한 부분부터 시작하고 싶습니다. (문제를 수정했습니다. 이것은 실제로 MySQL 복원 등에 관한 질문이 아닙니다.)

제가 하고 싶은 일은 백업 파일을 가져와 다음 backup.sql줄이 보일 때까지 파일의 시작 부분을 잘라내는 것입니다.

-- Table structure for `mytable`

그러면 그 이후의 모든 내용은 내 결과 파일에 저장됩니다 backup-secondhalf.sql. 파일이 bzip2로 압축되어 있다는 사실로 인해 다소 복잡하지만 그렇게 큰 문제는 아닙니다.

나는 이렇게 할 수 있다고 생각합니다 :

$ bunzip2 -c backup.sql.bz2 | grep --text --byte-offset --only-matching -e '--Table structure for table `mytable`' -m 1

이렇게 하면 트리밍하려는 파일의 바이트 오프셋이 제공됩니다.까지. 그 다음에:

$ bunzip2 -c backup.sql.bz2 | dd skip=[number from above] | bzip2 -c > backup-secondhalf.sql.bz2

불행하게도 이를 위해서는 파일에 대해 bunzip2를 두 번 실행하고 모든 바이트를 두 번 읽어야 합니다.

이 모든 것을 한 번에 할 수 있는 방법이 있나요?

내 sed-fu가 "정규 표현식까지 모든 줄을 삭제한 다음 파일의 나머지 부분을 통과시키십시오"라는 표현을 수행할 만큼 강력한지 잘 모르겠습니다.

이것은 Debian Linux에 있으므로 GNU 도구를 사용할 수 있습니다.

답변1

bunzip2 -c backup.sql.bz2 | \
  sed -n '/-- Table structure for `mytable`/,$p'

설명:

-n suppress automatic printing of pattern space

주소 범위 구성: 정규식으로 시작

/-- Table structure for  `mytable`/

다음으로 끝남

$ Match the last line.

명령

p Print the current pattern space.

편집: 데이터베이스를 덤프한 방법에 따라매우긴 줄. GNU sed는 사용 가능한 메모리 양까지 이를 처리할 수 있습니다.

답변2

참고: 실제 답변은 아닙니다.

이 문제를 해결하려는 동기가 부여되었기 때문에지금, 나는 grep내가 원하는 파일에서 오프셋을 찾는 데 사용했습니다. 그것은 훌륭하게 작동했습니다.

불행하게도 실행하려면 기본적으로 버퍼링이 없음을 의미하는 dd설정이 필요하며 ibs=1성능이 끔찍합니다. dd가 완료되기를 기다리는 동안 바이트를 건너뛰기 위해 나만의 맞춤형 C 프로그램을 작성하는 데 시간을 보냈습니다. 그 일을 하고 나니, 나 tail역시 쉽게 그 일을 할 수 있었을 것입니다.

$ bunzip2 -c restore.sql.bz2 | tail -c +[offset] | bzip2 -c > restore-trimmed.sql.bz2

나는 "이것은 내 질문에 대답하지 않습니다"라고 말합니다. 왜냐하면 여전히 파일을 두 번 통과해야 하기 때문입니다. 하나는 내가 찾고 있는 것의 오프셋을 찾기 위한 것이고 다른 하나는 파일을 다듬기 위한 것입니다.

내 맞춤 프로그램으로 돌아가면 다음을 구현할 수 있습니다.KMP프로그램의 "읽기 전용" 단계에서 그 다음에는 "모든 항목 읽기+쓰기"로 전환합니다.

답변3

그런 것이 효과가 있을지 궁금합니다.

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;
}

따라서 기본적으로 패턴 이후에 인쇄를 시작합니다. 데비안에서 perl chop.pl input_sql.bz2 | bzip2 > out.sql.bz2 필요한 것처럼 bzip2/gzip으로 직접 파이프할 수도 있습니다.libio-compress-perl

관련 정보