Saya menggunakan banyak grep awk sort di shell unix saya untuk bekerja dengan file teks kolom yang dipisahkan tab berukuran sedang (sekitar 10M-100M baris). Dalam hal ini unix shell adalah spreadsheet saya.
Tapi saya punya satu masalah besar, yaitu memilih catatan yang diberikan daftar ID.
Memiliki table.csv
file dengan format idtfootbar...
dan ids.csv
file dengan daftar id, hanya pilih catatan dari table.csv
dengan id ada di ids.csv
.
semacam https://stackoverflow.com/questions/13732295/extract-all-lines-from-text-file-based-on-a-given-list-of-ids tetapi dengan shell, bukan perl.
grep -F
jelas menghasilkan positif palsu jika id adalah lebar variabel.join
adalah utilitas yang tidak pernah saya ketahui. Pertama-tama, ini membutuhkan pengurutan alfabet (file saya biasanya diurutkan secara numerik), tetapi meskipun demikian saya tidak dapat membuatnya berfungsi tanpa mengeluh tentang urutan yang salah dan melewatkan beberapa catatan. Jadi saya tidak menyukainya.
grep -f terhadap file dengan ^idt
-s sangat lambat ketika jumlah id besar.awk
rumit.
Apakah ada solusi yang baik untuk ini? Adakah alat khusus untuk file yang dipisahkan tab? Fungsionalitas tambahan juga akan disambut baik.
UPD:sort
yang dikoreksi -> join
Jawaban yang Diterima:
Saya kira maksud Anda grep -f
bukan grep -F
tetapi Anda sebenarnya membutuhkan kombinasi keduanya dan -w
:
grep -Fwf ids.csv table.csv
Alasan Anda mendapatkan hasil positif palsu adalah (saya kira, Anda tidak menjelaskannya) karena jika sebuah id dapat dimasukkan ke dalam yang lain, maka keduanya akan dicetak. -w
menghilangkan masalah ini dan -F
memastikan pola Anda diperlakukan sebagai string, bukan ekspresi reguler. Dari 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.)
Jika positif palsu Anda karena ID dapat ada di bidang non-ID, ulangi file Anda sebagai gantinya:
while read pat; do grep -w "^$pat" table.csv; done < ids.csv
atau, lebih cepat:
xargs -I {} grep "^{}" table.csv < ids.csv
Secara pribadi, saya akan melakukan ini di perl
meskipun:
perl -lane 'BEGIN{open(A,"ids.csv"); while(<A>){chomp; $k{$_}++}}
print $_ if defined($k{$F[0]}); ' table.csv