現在、さらに大きなcsvファイル(3.000.000行)に対して、IDの大きなリスト(〜5000)をgrep
しようとしています。
Idファイルのidを含むすべてのcsv行が必要です。
私の素朴なアプローチは:
cat the_ids.txt | while read line
do
cat huge.csv | grep $line >> output_file
done
しかし、これには永遠に時間がかかります!
この問題に対するより効率的なアプローチはありますか?
試して
grep -f the_ids.txt huge.csv
さらに、パターンは固定文字列のように見えるため、-F
オプションはgrep
を高速化するかもしれません。
-F, --fixed-strings
Interpret PATTERN as a list of fixed strings, separated by
newlines, any of which is to be matched. (-F is specified by
POSIX.)
これにはgrep -f
を使用します。
grep -f the_ids.txt huge.csv > output_file
man grep
から:
-f FILE、-file = FILE
FILEからパターンを1行に1つずつ取得します。空のファイルにはパターンが含まれていないため、何にも一致しません。 (-fはPOSIXで指定されます。)
サンプル入力を提供する場合は、grep
条件をもう少し改善することもできます。
$ cat ids
11
23
55
$ cat huge.csv
hello this is 11 but
nothing else here
and here 23
bye
$ grep -f ids huge.csv
hello this is 11 but
and here 23
grep -f filter.txt data.txt
は、filter.txt
が数千行よりも大きい場合に手に負えなくなるため、このような状況には最適な選択肢ではありません。 grep -f
を使用している場合でも、いくつかの点に留意する必要があります。
-x
オプションを使用します-F
を使用します-w
オプションを使用していないときに部分一致を防ぐには、-x
を使用しますこの投稿には、このトピックに関する素晴らしい議論があります(大きなファイルのgrep -f
):
そして、この投稿はgrep -vf
について語っています:
要約すると、大きなファイルでgrep -f
を処理する最良の方法は次のとおりです:
行全体に一致:
awk 'FNR==NR {hash[$0]; next} $0 in hash' filter.txt data.txt > matching.txt
2番目のファイル内の特定のフィールドを一致させる(この例では「、」区切り文字とフィールド2を使用):
awk -F, 'FNR==NR {hash[$1]; next} $2 in hash' filter.txt data.txt > matching.txt
およびgrep -vf
の場合:
行全体に一致:
awk 'FNR==NR {hash[$0]; next} !($0 in hash)' filter.txt data.txt > not_matching.txt
2番目のファイル内の特定のフィールドを一致させる(この例では「、」区切り文字とフィールド2を使用):
awk -F, 'FNR==NR {hash[$0]; next} !($2 in hash)' filter.txt data.txt > not_matching.txt