때때로 여러 줄에 걸쳐 있는 레코드로 60GB 플랫 파일을 분할합니다.

때때로 여러 줄에 걸쳐 있는 레코드로 60GB 플랫 파일을 분할합니다.

데이터를 수동으로 입력하면 여러 줄 바꿈이 포함된 레코드로 데이터베이스가 오염될 수 있습니다. 단 하나의 열이 있는 거대한 60GB 플랫 파일의 시작과 끝에 큰따옴표가 있는 좋은 레코드의 경우 다음과 같이 항상 한 줄로만 구성되어야 합니다.

"이제 많은 미토콘드리아, 많은 원핵생물 및 일부 핵 게놈에 대한 완전한 서열을 이용할 수 있습니다."

잘못된 레코드의 경우 다음과 같이 무제한의 여러 줄에 걸쳐 있습니다.

“현재 흡연은 더 높은 위험과 강한 반비례 관계가 있습니다.

수반되는 위험 요인을 조정한 후의 모델입니다. 대 전혀

흡연자, 현재 흡연자는 고위험군에 걸릴 가능성이 현저히 낮았습니다.

무늬. "

이러한 여러 줄 레코드는 UNIX 명령이 다운스트림 파일 분할을 방지합니다 split. split이러한 여러 행을 단일 레코드로 지능적으로 인식할 수 있는 방법이 없으므로 단일 레코드가 별도의 파일로 분할될 수 있습니다. 아래 Perl은 이 큰 파일을 분할하기 전에 잘못된 줄을 병합하기에는 너무 느립니다. 2시간 이상 기다린 후에는 $count를 인쇄할 수 없기 때문입니다.

$file=$ARGV[0];
open(INFO, $file) or die("Could not open $file.");
open(OUT, ">out") or die("Could not open $file.");

$mergedline = "";
$count=0;
foreach $line (<INFO>)  {
    print $count++;
    if ($line =~ /^".*"\n$/) {
                print OUT $line;
                $mergedline = "";
                next;
        } elsif ($line =~ /"\n$/) {
                print OUT $mergedline;
                $mergedline = "";
                next;
        } else {
                chomp $line;
                $mergedline .= $line;
        }
}
close(INFO);

출력 파일이 "깨끗"하고 한 줄 레코드만 처리될 수 있도록 이 문제를 해결할 수 있는 편리한 UNIX 명령이 있습니까 split?

sed옵션처럼 보이지만 다음 게시물 중 어느 것도 질문에 대답하지 않습니다.

https://stackoverflow.com/questions/15758814/turning-multiple-lines-into-one-line-with-comma-separated-perl-sed-awk

https://stackoverflow.com/questions/11290616/sed-conditional-merge-of-multiple-lines

http://www.unix.com/shell-programming-and-scripting/80633-sed-combining-multiple-lines-into-one.html

게시 패턴이 너무 규칙적이고 일정하기 때문입니다.

답변1

sed분할선 연결 전용

sed ':a
/".*"$/b
N;s/\n/ /;ba' input >> output

내 시스템에서 10MB 파일을 처리하는 데 6초가 걸립니다. 60GB의 경우 10시간이 됩니다.

bbe조금 빠르다

bbe -b '/"/:/"/' -o output -e 'y/\n/ /' input

하지만 여전히 4초가 걸립니다.

유감스럽게도 이러한 스크립팅 언어는 매우 큰 파일에서 제대로 작동하는 도구가 아닙니다. 작은 프로그램을 작성해 보는 것은 어떨까요 C?

답변2

사용 예 gawk:

awk 'BEGIN {RS = "\"\n"} {++n; print $0"\""> n".txt"}' input

input이는 임의의 순서로 파일을 분할한 "다음 줄 바꿈( \n)을 사용하는 것을 의미합니다. 이는 따옴표 바로 뒤에 오지 않는 개행 문자를 무시하므로 여러 줄의 레코드가 보존됩니다. 이 예에서는 출력이 텍스트 파일에 기록되지만 해당 > n".txt"섹션을 제거하면 레코드를 파이프로 보낼 수 있습니다.

답변3

Perl루프를 사용하여 파일을 읽기 때문에 for속도가 느려집니다. 루프는 전체 파일을 한 번에 메모리에 로드하기 while때문에 루프를 사용해야 합니다 . for이것이 $count를 인쇄하는 데 시간이 오래 걸리는 이유입니다.

perl -ne '
   print,next if /^".*"$/m or /"$/m;
   chomp, $_ .= <>, redo unless eof;
' gene.data

관련 정보