UNIXシェルで多くのgrepawkソートを使用して、中サイズ(約10M〜100M行)のタブ区切りの列テキストファイルを処理します。この点で、unixシェルは私のスプレッドシートです。
しかし、私には1つの大きな問題があります。それは、IDのリストを指定してレコードを選択することです。
table.csv
がある idtfootbar...
形式のファイル およびids.csv
IDのリストを含むファイル、table.csv
からレコードのみを選択 ids.csv
にIDが存在する 。
https://stackoverflow.com/questions/13732295/extract-all-lines-from-text-file-based-on-a-given-list-of-idsの一種ですが、Perlではなくシェルを使用します。
grep -F
IDが可変幅の場合、明らかに誤検知が発生します。
join
私が理解できなかったユーティリティです。まず、アルファベット順の並べ替えが必要です(私のファイルは通常、数値で並べ替えられます)が、それでも、間違った順序について不平を言い、一部のレコードをスキップしない限り、機能させることはできません。だから私はそれが好きではありません。^idt
のファイルに対するgrep-f -IDの数が多い場合、sは非常に遅くなります。
awk
面倒です。
これに対する良い解決策はありますか?タブ区切りファイル用の特定のツールはありますか?追加機能も大歓迎です。
UPD:sort
を修正しました ->join
承認された回答:
grep -f
を意味していると思います grep -F
ではありません ただし、実際には両方と-w
の組み合わせが必要です :
grep -Fwf ids.csv table.csv
誤検知が発生した理由は(おそらく説明しなかったと思いますが)、IDを別のIDに含めることができる場合は、両方が出力されるためです。 -w
この問題を取り除き、-F
パターンが正規表現ではなく文字列として扱われるようにします。 man 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.)
-w, --word-regexp
Select only those lines containing matches that form whole
words. The test is that the matching substring must either be
at the beginning of the line, or preceded by a non-word
constituent character. Similarly, it must be either at the end
of the line or followed by a non-word constituent character.
Word-constituent characters are letters, digits, and the
underscore.
-f FILE, --file=FILE
Obtain patterns from FILE, one per line. The empty file
contains zero patterns, and therefore matches nothing. (-f is
specified by POSIX.)
IDが非IDフィールドに存在する可能性があるために誤検知が発生した場合は、代わりにファイルをループしてください:
while read pat; do grep -w "^$pat" table.csv; done < ids.csv
または、より速く:
xargs -I {} grep "^{}" table.csv < ids.csv
個人的には、これをperl
で行います ただし:
perl -lane 'BEGIN{open(A,"ids.csv"); while(<A>){chomp; $k{$_}++}}
print $_ if defined($k{$F[0]}); ' table.csv