2016-08-11 8 views
1

私は検索する847のキーワードのリストを持つファイル(queryids.txt)を持っています。私は約12の巨大なcsvファイルからキーワードをgrepする必要があります(最大2,184,820,000行を持っています)。最終的には、それをある種のデータベースにロードしますが、今は特定のキーワードをgrepする必要があります。巨大なCSVファイルの高速grep

私のコマンドは次のとおりです。私はこのようなbashスクリプトを書くことを考えています

LC_ALL=C fgrep -f queryids.txt subject.csv 

#!/bin/bash 

for f in *.csv 
do 
    (echo "Processing $f" 
    filename=$(basename "$f") 
    filename="${filename%.*}" 
    LC_ALL=C fgrep -f queryids.txt $f > $filename"_goi.csv") & 
done 

と私が使用してそれを実行します:nohup bash myscript.sh &

queryids.txtのルックスこのように:

ENST00000401850 
ENST00000249005 
ENST00000381278 
ENST00000483026 
ENST00000465765 
ENST00000269080 
ENST00000586539 
ENST00000588458 
ENST00000586292 
ENST00000591459 

対象ファイルは、次のようになります

target_id,length,eff_length,est_counts,tpm,id 
ENST00000619216.1,68,2.65769E1,0.5,0.300188,00065a62-5e18-4223-a884-12fca053a109 
ENST00000473358.1,712,5.39477E2,8.26564,0.244474,00065a62-5e18-4223-a884-12fca053a109 
ENST00000469289.1,535,3.62675E2,4.82917,0.212463,00065a62-5e18-4223-a884-12fca053a109 
ENST00000607096.1,138,1.92013E1,0,0,00065a62-5e18-4223-a884-12fca053a109 
ENST00000417324.1,1187,1.01447E3,0,0,00065a62-5e18-4223-a884-12fca053a109 

私は、これは長い時間がかかるだろう心配です。これを行うより速い方法がありますか?

ありがとうございます!私は、パフォーマンスを向上させるために提案することができ

+0

時間のほとんどは、CSVファイルを読み込む取られます。これは、ループをどのように構造化するかにかかわらず実行する必要があります。 'queryids.txt'は小さいので、各ファイルについてそれを再読み込みしても大きな違いはありません。 – Barmar

+0

質問を完成させるには、投稿した2つの入力ファイルの予想出力を含めるように[編集]してください。 –

+1

2本の_billion行のCSVファイルがありますか?_最終的には、それを何らかのデータベースにロードしますが、今のところは_私は10年ごとに毎年これを言ってきましたか? :)あなたの技術的な負債を食い止める! –

答えて

2

いくつかのこと:

  1. (..) &を使用して、サブシェルを起動する必要はありません、必要な場合は、中括弧{ ... } &を使用することができます。
  2. 使用grep -F(非正規表現または固定文字列検索)grep実行速度
  3. basenameコマンドを避け、このスクリプトを試してみてください

bash文字列操作を使用するようにする:私はあなたを示唆して

​​

これを小さなデータセットで実行して、パフォーマンスの向上を比較します。

+1

'fgrep'は' grep -F'に似ていますが、前者は後者を推奨していません。 – heemayl

+0

はいOPのスクリプトで 'fgrep'の使用を見落としました。 – anubhava

+0

ありがとう、私はそれを試みます。私はまた、より多くの文脈を与えるためにファイルの詳細を追加しました。 –

0

あなたは代わりに、これを試みることができる:それは文字列の比較ではなく、正規表現を使用しています

awk ' 
BEGIN { 
    while ((getline line < "queryids.txt") > 0 ) { 
     re = (re=="" ? "" : re "|") line 
    } 
} 
FNR==1 { close(out); out=FILENAME; sub(/\.[^.]+$/,"_goi&",out) } 
$0 ~ re { print > out } 
' *.csv 

- 事項はと、そうならば、我々は何を行うことができますかどうか、それはqueryids.txt内の値に依存について。実際にはのファイルが含まれているかどうかに応じてこれを行うより高速でより堅牢な方法があります。ファイルの内容のいくつかの例を含めると、さらに役立つかもしれません。私はあなたを参照してください

は現在、いくつかのサンプル入力を掲載しているし、実際に私たちは、ハッシュ・ルックアップを使用してより速く、より確実にこれを行うことができます。

awk ' 
BEGIN { 
    FS="." 
    while ((getline line < "queryids.txt") > 0 ) { 
     ids[line] 
    } 
} 
FNR==1 { close(out); out=FILENAME; sub(/\.[^.]+$/,"_goi&",out) } 
$1 in ids { print > out } 
' *.csv 
+0

ファイルの詳細を追加して、より多くのコンテキストを提供しました。 –

+0

最後にもっと速いアプローチを示すために私の答えを更新しました。 –

+0

'grep -f'が内部的にこれをしていなかったのは、実際にはもっと速いのですが、私は驚いています。 'grep'はかなりうまく最適化されています。 'awk'でファイルを1行ずつ走査するのが' grep'自身の検索よりも速ければ驚いています。 – chepner

関連する問題