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

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

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

"수많은 미토콘드리아 게놈, 원핵생물 게놈, 핵 게놈의 완전한 서열이 현재 이용 가능합니다."

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

"현재 흡연은 고위험군과 강력하고 반비례합니다.

수반되는 위험 요인을 조정한 후 패턴. 결코 그렇지 않은 것에 비해

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

무늬. "

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

$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);

이 문제를 해결하여 출력 파일이 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사용해야 합니다 . 그렇기 때문에 $count를 인쇄하는 데 시간이 오래 걸립니다.whilefor

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

관련 정보