데이터를 수동으로 입력하면 여러 개행 문자가 포함된 레코드로 데이터베이스가 오염됩니다. 단일 열만 있는 거대한 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/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를 인쇄하는 데 시간이 오래 걸립니다.while
for
perl -ne '
print,next if /^".*"$/m or /"$/m;
chomp, $_ .= <>, redo unless eof;
' gene.data