分割一個 60GB 的平面文件,記錄偶爾跨越多行

分割一個 60GB 的平面文件,記錄偶爾跨越多行

手動輸入資料會使資料庫被包含多個換行符的記錄污染。對於只有一列的 60GB 巨大平面檔案中開頭和結尾用雙引號分隔的良好記錄,它們應該始終只跨越一行,如下所示:

“現在可以獲得許多粒線體、許多原核生物和一些核基因組的完整序列。”

對於不良記錄,它們跨越無限數量的多行,如下所示:

「目前吸菸與高風險呈現強烈負相關。

調整伴隨風險因子後的模式。相對於從不

吸煙者,目前吸煙者患高風險的可能性明顯降低

圖案。 」

這些多行記錄禁止 UNIX 指令進行下游檔案分割splitsplit無法智慧地將這些多行識別為單一記錄,這可能導致將單一記錄拆分為單獨的檔案。下面的 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

在我的系統上處理一個 10 MB 的檔案需要 6 秒。對於 60 GB,這將是 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

相關內容